From cba2ac6ef10304047f7a7941e6c8912573ebc3c6 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Thu, 22 Dec 2016 13:06:44 +0100
Subject: [PATCH 001/101] 5.5.53-38.5
---
storage/xtradb/include/univ.i | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index cc589166f8d..d198fbf021b 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -64,7 +64,7 @@ component, i.e. we show M.N.P as M.N */
(INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 38.3
+#define PERCONA_INNODB_VERSION 38.5
#endif
#define INNODB_VERSION_STR MYSQL_SERVER_VERSION
From 9181a561a68d9b18331cc4c0a9b9fdc704edb300 Mon Sep 17 00:00:00 2001
From: Balasubramanian Kandasamy
Date: Mon, 27 Feb 2017 17:20:51 +0530
Subject: [PATCH 002/101] Raise version number after cloning 5.5.55
---
VERSION | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/VERSION b/VERSION
index bc0b19220b6..ade2e129c54 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
MYSQL_VERSION_MAJOR=5
MYSQL_VERSION_MINOR=5
-MYSQL_VERSION_PATCH=55
+MYSQL_VERSION_PATCH=56
MYSQL_VERSION_EXTRA=
From e619295e1b480a24ee9740641ce69b8a412e1fc9 Mon Sep 17 00:00:00 2001
From: Sujatha Sivakumar
Date: Tue, 28 Feb 2017 10:00:51 +0530
Subject: [PATCH 003/101] Bug#24901077: RESET SLAVE ALL DOES NOT ALWAYS RESET
SLAVE
Description:
============
If you have a relay log index file that has ended up with
some relay log files that do not exists, then RESET SLAVE
ALL is not enough to get back to a clean state.
Analysis:
=========
In the bug scenario slave server is in stopped state and
some of the relay logs got deleted but the relay log index
file is not updated.
During slave server restart replication initialization fails
as some of the required relay logs are missing. User
executes RESET SLAVE/RESET SLAVE ALL command to start a
clean slave. As per the documentation RESET SLAVE command
clears the master info and relay log info repositories,
deletes all the relay log files, and starts a new relay log
file. But in a scenario where the slave server's
Relay_log_info object is not initialized slave will not
purge the existing relay logs. Hence the index file still
remains in a bad state. Users will not be able to start
the slave unless these files are cleared.
Fix:
===
RESET SLAVE/RESET SLAVE ALL commands should do the cleanup
even in a scenario where Relay_log_info object
initialization failed.
Backported a flag named 'error_on_rli_init_info' which is
required to identify slave's Relay_log_info object
initialization failure. This flag exists in MySQL-5.6
onwards as part of BUG#14021292 fix.
During RESET SLAVE/RESET SLAVE ALL execution this flag
indicates the Relay_log_info initialization failure.
In such a case open the relay log index/relay log files
and do the required clean up.
---
.../suite/rpl/r/rpl_reset_slave_fail.result | 29 ++++++
.../suite/rpl/t/rpl_reset_slave_fail.test | 91 +++++++++++++++++++
sql/rpl_mi.cc | 3 +-
sql/rpl_rli.cc | 50 ++++++++--
sql/rpl_rli.h | 11 ++-
sql/slave.cc | 4 +-
sql/sql_repl.cc | 3 +-
7 files changed, 176 insertions(+), 15 deletions(-)
create mode 100644 mysql-test/suite/rpl/r/rpl_reset_slave_fail.result
create mode 100644 mysql-test/suite/rpl/t/rpl_reset_slave_fail.test
diff --git a/mysql-test/suite/rpl/r/rpl_reset_slave_fail.result b/mysql-test/suite/rpl/r/rpl_reset_slave_fail.result
new file mode 100644
index 00000000000..6b60e021778
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_reset_slave_fail.result
@@ -0,0 +1,29 @@
+include/master-slave.inc
+[connection master]
+CREATE TABLE t1 (c1 INT);
+INSERT INTO t1 (c1) VALUES (1);
+include/stop_slave_sql.inc
+FLUSH LOGS;
+FLUSH LOGS;
+INSERT INTO t1 (c1) VALUES (2);
+include/sync_slave_io_with_master.inc
+call mtr.add_suppression("File '.*slave-relay-bin.");
+call mtr.add_suppression("Could not open log file");
+call mtr.add_suppression("Failed to open the relay log");
+call mtr.add_suppression("Failed to initialize the master info structure");
+include/rpl_stop_server.inc [server_number=2]
+# Removing file(s)
+include/rpl_start_server.inc [server_number=2]
+START SLAVE;
+ERROR HY000: Could not initialize master info structure; more error messages can be found in the MySQL error log
+START SLAVE;
+ERROR HY000: Could not initialize master info structure; more error messages can be found in the MySQL error log
+RESET SLAVE;
+DROP TABLE t1;
+START SLAVE UNTIL MASTER_LOG_FILE= 'MASTER_LOG_FILE', MASTER_LOG_POS= MASTER_LOG_POS;;
+include/wait_for_slave_sql_to_stop.inc
+include/stop_slave_io.inc
+include/start_slave.inc
+include/diff_tables.inc [master:t1, slave:t1]
+DROP TABLE t1;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_reset_slave_fail.test b/mysql-test/suite/rpl/t/rpl_reset_slave_fail.test
new file mode 100644
index 00000000000..021dc76d50c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_reset_slave_fail.test
@@ -0,0 +1,91 @@
+###############################################################################
+# Bug#24901077: RESET SLAVE ALL DOES NOT ALWAYS RESET SLAVE
+#
+# Problem:
+# =======
+# If you have a relay log index file that has ended up with
+# some relay log files that do not exists, then RESET SLAVE
+# ALL is not enough to get back to a clean state.
+###############################################################################
+# Remove all slave-relay-bin.0* files (do not remove slave-relay-bin.index)
+# During server restart rli initialization will fail as there are no
+# relay logs. In case of bug RESET SLAVE will not do the required clean up
+# as rli is not inited and subsequent START SLAVE will fail.
+# Disable "Warning 1612 Being purged log ./slave-relay-bin.0* was not found"
+# because it is different on Unix and Windows systems.
+
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+--connection master
+CREATE TABLE t1 (c1 INT);
+INSERT INTO t1 (c1) VALUES (1);
+--sync_slave_with_master
+
+--connection slave
+--source include/stop_slave_sql.inc
+--let $MYSQLD_SLAVE_DATADIR= `select @@datadir`
+
+--connection master
+# Generate more relay logs on slave.
+FLUSH LOGS;
+FLUSH LOGS;
+INSERT INTO t1 (c1) VALUES (2);
+
+--source include/sync_slave_io_with_master.inc
+call mtr.add_suppression("File '.*slave-relay-bin.");
+call mtr.add_suppression("Could not open log file");
+call mtr.add_suppression("Failed to open the relay log");
+call mtr.add_suppression("Failed to initialize the master info structure");
+
+# Stop slave
+--let $rpl_server_number= 2
+--source include/rpl_stop_server.inc
+
+# Delete file(s)
+--echo # Removing $remove_pattern file(s)
+--let $remove_pattern= slave-relay-bin.0*
+--remove_files_wildcard $MYSQLD_SLAVE_DATADIR $remove_pattern
+
+# Start slave
+--let $rpl_server_number= 2
+--source include/rpl_start_server.inc
+
+# Start slave must fail because of the removed file(s).
+--error ER_MASTER_INFO
+START SLAVE;
+
+# Try a second time, it must fail again.
+--error ER_MASTER_INFO
+START SLAVE;
+
+# Retrieve master executed position before reset slave.
+--let $master_exec_file= query_get_value("SHOW SLAVE STATUS", Relay_Master_Log_File, 1)
+--let $master_exec_pos= query_get_value("SHOW SLAVE STATUS", Exec_Master_Log_Pos, 1)
+
+# Reset slave.
+# Disable "Warning 1612 Being purged log ./slave-relay-bin.0* was not found"
+# because it is different on Unix and Windows systems.
+--disable_warnings
+RESET SLAVE;
+--enable_warnings
+DROP TABLE t1;
+--replace_result $master_exec_file MASTER_LOG_FILE $master_exec_pos MASTER_LOG_POS
+--eval START SLAVE UNTIL MASTER_LOG_FILE= '$master_exec_file', MASTER_LOG_POS= $master_exec_pos;
+--source include/wait_for_slave_sql_to_stop.inc
+--source include/stop_slave_io.inc
+
+# Start slave.
+--source include/start_slave.inc
+
+--connection master
+--sync_slave_with_master
+# Check consistency.
+--let $diff_tables= master:t1, slave:t1
+--source include/diff_tables.inc
+
+# Cleanup
+--connection master
+DROP TABLE t1;
+--sync_slave_with_master
+--source include/rpl_end.inc
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index ee5caced11a..a78b31cbaed 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -551,7 +551,6 @@ void end_master_info(Master_info* mi)
if (!mi->inited)
DBUG_VOID_RETURN;
- end_relay_log_info(&mi->rli);
if (mi->fd >= 0)
{
end_io_cache(&mi->file);
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index e4f2e4fd382..65ab264e1f3 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -41,7 +41,8 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery)
no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id),
info_fd(-1), cur_log_fd(-1), relay_log(&sync_relaylog_period),
sync_counter(0), is_relay_log_recovery(is_slave_recovery),
- save_temporary_tables(0), cur_log_old_open_count(0), group_relay_log_pos(0),
+ save_temporary_tables(0), cur_log_old_open_count(0),
+ error_on_rli_init_info(false), group_relay_log_pos(0),
event_relay_log_pos(0),
#if HAVE_purify
is_fake(FALSE),
@@ -108,7 +109,7 @@ int init_relay_log_info(Relay_log_info* rli,
const char* info_fname)
{
char fname[FN_REFLEN+128];
- int info_fd;
+ int info_fd= -1;
const char* msg = 0;
int error = 0;
DBUG_ENTER("init_relay_log_info");
@@ -118,6 +119,8 @@ int init_relay_log_info(Relay_log_info* rli,
DBUG_RETURN(0);
fn_format(fname, info_fname, mysql_data_home, "", 4+32);
mysql_mutex_lock(&rli->data_lock);
+ if (rli->error_on_rli_init_info)
+ goto err;
info_fd = rli->info_fd;
rli->cur_log_fd = -1;
rli->slave_skip_counter=0;
@@ -351,11 +354,14 @@ Failed to open the existing relay log info file '%s' (errno %d)",
goto err;
}
rli->inited= 1;
+ rli->error_on_rli_init_info= false;
mysql_mutex_unlock(&rli->data_lock);
DBUG_RETURN(error);
err:
- sql_print_error("%s", msg);
+ rli->error_on_rli_init_info= true;
+ if (msg)
+ sql_print_error("%s", msg);
end_io_cache(&rli->info_file);
if (info_fd >= 0)
mysql_file_close(info_fd, MYF(0));
@@ -942,6 +948,8 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
const char** errmsg)
{
int error=0;
+ const char *ln;
+ char name_buf[FN_REFLEN];
DBUG_ENTER("purge_relay_logs");
/*
@@ -968,12 +976,34 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
if (!rli->inited)
{
DBUG_PRINT("info", ("rli->inited == 0"));
- DBUG_RETURN(0);
+ if (rli->error_on_rli_init_info)
+ {
+ ln= rli->relay_log.generate_name(opt_relay_logname, "-relay-bin",
+ 1, name_buf);
+
+ if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln, TRUE))
+ {
+ sql_print_error("Unable to purge relay log files. Failed to open relay "
+ "log index file:%s.", rli->relay_log.get_index_fname());
+ DBUG_RETURN(1);
+ }
+ if (rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0,
+ (max_relay_log_size ? max_relay_log_size :
+ max_binlog_size), 1, TRUE))
+ {
+ sql_print_error("Unable to purge relay log files. Failed to open relay "
+ "log file:%s.", rli->relay_log.get_log_fname());
+ DBUG_RETURN(1);
+ }
+ }
+ else
+ DBUG_RETURN(0);
+ }
+ else
+ {
+ DBUG_ASSERT(rli->slave_running == 0);
+ DBUG_ASSERT(rli->mi->slave_running == 0);
}
-
- DBUG_ASSERT(rli->slave_running == 0);
- DBUG_ASSERT(rli->mi->slave_running == 0);
-
rli->slave_skip_counter=0;
mysql_mutex_lock(&rli->data_lock);
@@ -1013,6 +1043,8 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
rli->group_relay_log_pos,
0 /* do not need data lock */, errmsg, 0);
+ if (!rli->inited && rli->error_on_rli_init_info)
+ rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
err:
#ifndef DBUG_OFF
char buf[22];
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index dceeec9e777..89865a9f55c 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -153,7 +153,14 @@ public:
a different log under our feet
*/
uint32 cur_log_old_open_count;
-
+
+ /*
+ If on init_info() call error_on_rli_init_info is true that means
+ that previous call to init_info() terminated with an error, RESET
+ SLAVE must be executed and the problem fixed manually.
+ */
+ bool error_on_rli_init_info;
+
/*
Let's call a group (of events) :
- a transaction
diff --git a/sql/slave.cc b/sql/slave.cc
index acf68e231f3..1e641ac6d7e 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -881,6 +881,7 @@ void close_active_mi()
if (active_mi)
{
end_master_info(active_mi);
+ end_relay_log_info(&active_mi->rli);
delete active_mi;
active_mi= 0;
}
@@ -4165,6 +4166,7 @@ void end_relay_log_info(Relay_log_info* rli)
{
DBUG_ENTER("end_relay_log_info");
+ rli->error_on_rli_init_info= false;
if (!rli->inited)
DBUG_VOID_RETURN;
if (rli->info_fd >= 0)
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 8bbb8c52d95..ecbeff87a61 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1313,6 +1313,7 @@ int reset_slave(THD *thd, Master_info* mi)
// close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0
end_master_info(mi);
+ end_relay_log_info(&mi->rli);
// and delete these two files
fn_format(fname, master_info_file, mysql_data_home, "", 4+32);
if (mysql_file_stat(key_file_master_info, fname, &stat_area, MYF(0)) &&
From af84921d263b8bb1d1a06989794db07394f94e21 Mon Sep 17 00:00:00 2001
From: Karthik Kamath
Date: Thu, 9 Mar 2017 14:57:20 +0530
Subject: [PATCH 004/101] BUG#24807826: UINT3KORR SHOULD STOP READING FOUR
INSTEAD OF THREE BYTES ON X86
Analysis:
=========
The macro uint3korr reads 4 bytes of data instead of 3 on
on x86 machines.
Multiple definitions were created for this macro for
optimization in WIN32. The idea was to optimize reading of
3 byte ints by reading an ordinary int and masking away the
unused byte. However this is an undefined behavior. It will
be an issue unless users are aware of allocating an extra
byte for using this macro.
Fix:
====
Removing the definition which reads 4 bytes of data. The
only definition of this macro would now read just 3 bytes
of data thus prohibiting the usage of an extra byte.
Note:
=====
This is a backport of Patches #5 and #6 for Bug#17922198.
---
include/my_global.h | 12 +-----------
sql/net_serv.cc | 15 ++++++---------
sql/records.cc | 5 ++---
3 files changed, 9 insertions(+), 23 deletions(-)
diff --git a/include/my_global.h b/include/my_global.h
index 0d43964234b..695884cb6c6 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1064,19 +1064,9 @@ typedef char my_bool; /* Small bool */
((uint32) (uchar) (A)[0])))
#define sint4korr(A) (*((long *) (A)))
#define uint2korr(A) (*((uint16 *) (A)))
-#if defined(HAVE_purify) && !defined(_WIN32)
#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16))
-#else
-/*
- ATTENTION !
-
- Please, note, uint3korr reads 4 bytes (not 3) !
- It means, that you have to provide enough allocated space !
-*/
-#define uint3korr(A) (long) (*((unsigned int *) (A)) & 0xFFFFFF)
-#endif /* HAVE_purify && !_WIN32 */
#define uint4korr(A) (*((uint32 *) (A)))
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 9c0c84bb292..b2c36f7c29c 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -179,12 +179,10 @@ my_bool net_realloc(NET *net, size_t length)
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
/*
We must allocate some extra bytes for the end 0 and to be able to
- read big compressed blocks + 1 safety byte since uint3korr() in
- my_real_read() may actually read 4 bytes depending on build flags and
- platform.
+ read big compressed blocks in my_real_read().
*/
if (!(buff= (uchar*) my_realloc((char*) net->buff, pkt_length +
- NET_HEADER_SIZE + COMP_HEADER_SIZE + 1,
+ NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
{
/* @todo: 1 and 2 codes are identical. */
@@ -951,12 +949,11 @@ my_real_read(NET *net, size_t *complen)
if (net->compress)
{
/*
- The following uint3korr() may read 4 bytes, so make sure we don't
- read unallocated or uninitialized memory. The right-hand expression
- must match the size of the buffer allocated in net_realloc().
+ The right-hand expression must match the size of the buffer
+ allocated in net_realloc().
*/
DBUG_ASSERT(net->where_b + NET_HEADER_SIZE + sizeof(uint32) <=
- net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1);
+ net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE);
/*
If the packet is compressed then complen > 0 and contains the
number of bytes in the uncompressed packet
diff --git a/sql/records.cc b/sql/records.cc
index 7f74b84b2d7..ae7ec74c17d 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -589,10 +589,9 @@ static int init_rr_cache(THD *thd, READ_RECORD *info)
rec_cache_size= info->cache_records*info->reclength;
info->rec_cache_size= info->cache_records*info->ref_length;
- // We have to allocate one more byte to use uint3korr (see comments for it)
if (info->cache_records <= 2 ||
!(info->cache=(uchar*) my_malloc_lock(rec_cache_size+info->cache_records*
- info->struct_length+1,
+ info->struct_length,
MYF(0))))
DBUG_RETURN(1);
#ifdef HAVE_purify
From ec2a6b6035ed842e39bcecc2c62c39758bda02fb Mon Sep 17 00:00:00 2001
From: Terje Rosten
Date: Wed, 8 Mar 2017 08:29:02 +0100
Subject: [PATCH 005/101] BUG#25364806 MYSQLD_SAFE FAILING TO START IF DATADIR
GIVEN IS NOT ABSOLUTE PATH
mysqld_safe is working on real files, however passing these file paths
as is to mysqld as options gives different meaning when paths are
relative.
mysqld_safe uses current working directory as basedir for relative paths,
while mysqld uses $datadir as basedir.
---
scripts/mysqld_safe.sh | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index 7116211f8e6..32f489f2a09 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -24,7 +24,9 @@ want_syslog=0
syslog_tag=
user='@MYSQLD_USER@'
pid_file=
+pid_file_append=
err_log=
+err_log_append=
syslog_tag_mysqld=mysqld
syslog_tag_mysqld_safe=mysqld_safe
@@ -582,15 +584,17 @@ then
err_log="$err_log".err
fi
+ err_log_append="$err_log"
case "$err_log" in
/* ) ;;
* ) err_log="$DATADIR/$err_log" ;;
esac
else
err_log=$DATADIR/`@HOSTNAME@`.err
+ err_log_append=`@HOSTNAME@`.err
fi
- append_arg_to_args "--log-error=$err_log"
+ append_arg_to_args "--log-error=$err_log_append"
if [ $want_syslog -eq 1 ]
then
@@ -700,13 +704,15 @@ fi
if test -z "$pid_file"
then
pid_file="$DATADIR/`@HOSTNAME@`.pid"
+ pid_file_append="`@HOSTNAME@`.pid"
else
+ pid_file_append="$pid_file"
case "$pid_file" in
/* ) ;;
* ) pid_file="$DATADIR/$pid_file" ;;
esac
fi
-append_arg_to_args "--pid-file=$pid_file"
+append_arg_to_args "--pid-file=$pid_file_append"
if test -n "$mysql_unix_port"
then
From 2531c8dcd152bedeeebfe07d5e4a29bd84357c27 Mon Sep 17 00:00:00 2001
From: Ramil Kalimullin
Date: Fri, 10 Mar 2017 01:19:50 +0400
Subject: [PATCH 006/101] BUG#25575605: SETTING --SSL-MODE=REQUIRED SENDS
CREDENTIALS BEFORE VERIFYING SSL CONNECTION
MYSQL_OPT_SSL_MODE option introduced.
It is set in case of --ssl-mode=REQUIRED and permits only SSL connection.
---
client/client_priv.h | 34 +++++++++++++-----
client/mysql.cc | 6 ++--
client/mysql_upgrade.c | 6 ++--
client/mysqladmin.cc | 6 ++--
client/mysqlcheck.c | 4 +--
client/mysqldump.c | 4 +--
client/mysqlimport.c | 4 +--
client/mysqlshow.c | 4 +--
client/mysqlslap.c | 5 +--
client/mysqltest.cc | 6 ++--
include/mysql.h | 9 +++--
include/mysql.h.pp | 6 +++-
include/sql_common.h | 3 +-
include/sslopt-case.h | 4 +--
include/sslopt-vars.h | 6 ++--
mysql-test/r/ssl_mode.result | 6 ++--
mysql-test/r/ssl_mode_no_ssl.result | 22 ++++++------
sql-common/client.c | 54 +++++++++++++++++++++++++++--
18 files changed, 134 insertions(+), 55 deletions(-)
diff --git a/client/client_priv.h b/client/client_priv.h
index e53ced7e790..fb83ce9cc8b 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -115,13 +115,15 @@ enum options_client
/**
Wrapper for mysql_real_connect() that checks if SSL connection is establised.
- The function calls mysql_real_connect() first, then if given ssl_required==TRUE
- argument (i.e. --ssl-mode=REQUIRED option used) checks current SSL chiper to
- ensure that SSL is used for current connection.
- Otherwise it returns NULL and sets errno to CR_SSL_CONNECTION_ERROR.
+ The function calls mysql_real_connect() first. Then, if the ssl_required
+ argument is TRUE (i.e., the --ssl-mode=REQUIRED option was specified), it
+ checks the current SSL cipher to ensure that SSL is used for the current
+ connection. Otherwise, it returns NULL and sets errno to
+ CR_SSL_CONNECTION_ERROR.
- All clients (except mysqlbinlog which disregards SSL options) use this function
- instead of mysql_real_connect() to handle --ssl-mode=REQUIRED option.
+ All clients (except mysqlbinlog, which disregards SSL options) use this
+ function instead of mysql_real_connect() to handle the --ssl-mode=REQUIRED
+ option.
*/
MYSQL *mysql_connect_ssl_check(MYSQL *mysql_arg, const char *host,
const char *user, const char *passwd,
@@ -129,8 +131,22 @@ MYSQL *mysql_connect_ssl_check(MYSQL *mysql_arg, const char *host,
const char *unix_socket, ulong client_flag,
my_bool ssl_required __attribute__((unused)))
{
- MYSQL *mysql= mysql_real_connect(mysql_arg, host, user, passwd, db, port,
- unix_socket, client_flag);
+ MYSQL *mysql;
+
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
+ enum mysql_ssl_mode opt_ssl_mode= SSL_MODE_REQUIRED;
+ if (ssl_required &&
+ mysql_options(mysql_arg, MYSQL_OPT_SSL_MODE, (char *) &opt_ssl_mode))
+ {
+ NET *net= &mysql_arg->net;
+ net->last_errno= CR_SSL_CONNECTION_ERROR;
+ strmov(net->last_error, "Client library doesn't support MYSQL_SSL_REQUIRED option");
+ strmov(net->sqlstate, "HY000");
+ return NULL;
+ }
+#endif
+ mysql= mysql_real_connect(mysql_arg, host, user, passwd, db, port,
+ unix_socket, client_flag);
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
if (mysql && /* connection established. */
ssl_required && /* --ssl-mode=REQUIRED. */
diff --git a/client/mysql.cc b/client/mysql.cc
index cdc2ab0d6e0..2269563814c 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1318,7 +1318,7 @@ sig_handler handle_sigint(int sig)
kill_mysql= mysql_init(kill_mysql);
if (!mysql_connect_ssl_check(kill_mysql, current_host, current_user, opt_password,
"", opt_mysql_port, opt_mysql_unix_port, 0,
- opt_ssl_required))
+ opt_ssl_mode == SSL_MODE_REQUIRED))
{
tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n");
goto err;
@@ -4461,7 +4461,7 @@ sql_real_connect(char *host,char *database,char *user,char *password,
if (!mysql_connect_ssl_check(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port,
connect_flag | CLIENT_MULTI_STATEMENTS,
- opt_ssl_required))
+ opt_ssl_mode == SSL_MODE_REQUIRED))
{
if (!silent ||
(mysql_errno(&mysql) != CR_CONN_HOST_ERROR &&
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 507df6f7843..be0af089027 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -387,9 +387,11 @@ static int run_tool(char *tool_path, DYNAMIC_STRING *ds_res, ...)
va_end(args);
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
/* If given --ssl-mode=REQUIRED propagate it to the tool. */
- if (opt_ssl_required)
+ if (opt_ssl_mode == SSL_MODE_REQUIRED)
dynstr_append(&ds_cmdline, "--ssl-mode=REQUIRED");
+#endif
#ifdef __WIN__
dynstr_append(&ds_cmdline, "\"");
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index c03b37ab165..ae9db85b917 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -519,8 +519,8 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
for (;;)
{
if (mysql_connect_ssl_check(mysql, host, user, opt_password, NullS,
- tcp_port, unix_port,
- CLIENT_REMEMBER_OPTIONS, opt_ssl_required))
+ tcp_port, unix_port, CLIENT_REMEMBER_OPTIONS,
+ opt_ssl_mode == SSL_MODE_REQUIRED))
{
mysql->reconnect= 1;
if (info)
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 55b941e7f1a..7822460e341 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -907,7 +907,7 @@ static int dbConnect(char *host, char *user, char *passwd)
if (!(sock = mysql_connect_ssl_check(&mysql_connection, host, user, passwd,
NULL, opt_mysql_port,
opt_mysql_unix_port, 0,
- opt_ssl_required)))
+ opt_ssl_mode == SSL_MODE_REQUIRED)))
{
DBerror(&mysql_connection, "when trying to connect");
return 1;
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 00265def489..fcd29e26fe3 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1501,7 +1501,7 @@ static int connect_to_db(char *host, char *user,char *passwd)
if (!(mysql= mysql_connect_ssl_check(&mysql_connection, host, user,
passwd, NULL, opt_mysql_port,
opt_mysql_unix_port, 0,
- opt_ssl_required)))
+ opt_ssl_mode == SSL_MODE_REQUIRED)))
{
DB_error(&mysql_connection, "when trying to connect");
DBUG_RETURN(1);
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 5841c0b855a..bab43356bc7 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -463,7 +463,7 @@ static MYSQL *db_connect(char *host, char *database,
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
if (!(mysql_connect_ssl_check(mysql, host, user, passwd, database,
opt_mysql_port, opt_mysql_unix_port,
- 0, opt_ssl_required)))
+ 0, opt_ssl_mode == SSL_MODE_REQUIRED)))
{
ignore_errors=0; /* NO RETURN FROM db_error */
db_error(mysql);
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index d0390ec443b..bd7a37f93b4 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -142,7 +142,7 @@ int main(int argc, char **argv)
if (!(mysql_connect_ssl_check(&mysql, host, user, opt_password,
(first_argument_uses_wildcards) ? "" :
argv[0], opt_mysql_port, opt_mysql_unix_port,
- 0, opt_ssl_required)))
+ 0, opt_ssl_mode == SSL_MODE_REQUIRED)))
{
fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
exit(1);
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index eb2b577948c..aa312339e87 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -357,7 +357,8 @@ int main(int argc, char **argv)
{
if (!(mysql_connect_ssl_check(&mysql, host, user, opt_password,
NULL, opt_mysql_port, opt_mysql_unix_port,
- connect_flags, opt_ssl_required)))
+ connect_flags,
+ opt_ssl_mode == SSL_MODE_REQUIRED)))
{
fprintf(stderr,"%s: Error when connecting to server: %s\n",
my_progname,mysql_error(&mysql));
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 79d448cf811..e5f9b11fe76 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -5283,7 +5283,7 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host,
host, port, sock, user, name, failed_attempts);
while(!mysql_connect_ssl_check(mysql, host,user, pass, db, port, sock,
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS,
- opt_ssl_required))
+ opt_ssl_mode == SSL_MODE_REQUIRED))
{
/*
Connect failed
@@ -5385,7 +5385,7 @@ int connect_n_handle_errors(struct st_command *command,
while (!mysql_connect_ssl_check(con, host, user, pass, db, port,
sock ? sock: 0, CLIENT_MULTI_STATEMENTS,
- opt_ssl_required))
+ opt_ssl_mode == SSL_MODE_REQUIRED))
{
/*
If we have used up all our connections check whether this
diff --git a/include/mysql.h b/include/mysql.h
index da29cb342cc..7ebf2f725a2 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -167,7 +167,7 @@ enum mysql_option
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH,
- MYSQL_ENABLE_CLEARTEXT_PLUGIN
+ MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE
};
/**
@@ -224,6 +224,11 @@ enum mysql_protocol_type
MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY
};
+enum mysql_ssl_mode
+{
+ SSL_MODE_REQUIRED= 3
+};
+
typedef struct character_set
{
unsigned int number; /* character set number */
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index c2c5ba35044..0f292d921ee 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -263,7 +263,7 @@ enum mysql_option
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH,
- MYSQL_ENABLE_CLEARTEXT_PLUGIN
+ MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE
};
struct st_mysql_options_extention;
struct st_mysql_options {
@@ -307,6 +307,10 @@ enum mysql_protocol_type
MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET,
MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY
};
+enum mysql_ssl_mode
+{
+ SSL_MODE_REQUIRED= 3
+};
typedef struct character_set
{
unsigned int number;
diff --git a/include/sql_common.h b/include/sql_common.h
index a2ea3ac45e7..05bbb5a4f53 100644
--- a/include/sql_common.h
+++ b/include/sql_common.h
@@ -1,7 +1,7 @@
#ifndef SQL_COMMON_INCLUDED
#define SQL_COMMON_INCLUDED
-/* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@ struct st_mysql_options_extention {
char *plugin_dir;
char *default_auth;
my_bool enable_cleartext_plugin;
+ unsigned int ssl_mode;
};
typedef struct st_mysql_methods
diff --git a/include/sslopt-case.h b/include/sslopt-case.h
index 57702b3b352..0fddafc4fa9 100644
--- a/include/sslopt-case.h
+++ b/include/sslopt-case.h
@@ -1,7 +1,7 @@
#ifndef SSLOPT_CASE_INCLUDED
#define SSLOPT_CASE_INCLUDED
-/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -38,7 +38,7 @@
exit(1);
}
else
- opt_ssl_required= 1;
+ opt_ssl_mode= SSL_MODE_REQUIRED;
break;
#endif /* MYSQL_CLIENT */
#endif
diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h
index 6c9bd4296ef..a037538f693 100644
--- a/include/sslopt-vars.h
+++ b/include/sslopt-vars.h
@@ -1,7 +1,7 @@
#ifndef SSLOPT_VARS_INCLUDED
#define SSLOPT_VARS_INCLUDED
-/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -31,11 +31,11 @@ SSL_STATIC char *opt_ssl_key = 0;
#ifdef MYSQL_CLIENT
SSL_STATIC my_bool opt_ssl_verify_server_cert= 0;
-SSL_STATIC my_bool opt_ssl_required= 0;
+SSL_STATIC uint opt_ssl_mode= 0;
#endif /* MYSQL_CLIENT */
#else /* HAVE_OPENSSL */
-#define opt_ssl_required 0
+#define opt_ssl_mode 0
#endif /* HAVE_OPENSSL */
#endif /* SSLOPT_VARS_INCLUDED */
diff --git a/mysql-test/r/ssl_mode.result b/mysql-test/r/ssl_mode.result
index 38fc4e1dca2..c02a50bdcbd 100644
--- a/mysql-test/r/ssl_mode.result
+++ b/mysql-test/r/ssl_mode.result
@@ -37,8 +37,8 @@ DROP TABLE t1;
# mysql
Unknown value to --ssl-mode: ''. Use --ssl-mode=REQUIRED
Unknown value to --ssl-mode: 'DERIUQER'. Use --ssl-mode=REQUIRED
-ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections
-ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections
-ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections
+ERROR 2026 (HY000): SSL connection error: Client is not configured to use SSL
+ERROR 2026 (HY000): SSL connection error: Client is not configured to use SSL
+ERROR 2026 (HY000): SSL connection error: Client is not configured to use SSL
End of tests
diff --git a/mysql-test/r/ssl_mode_no_ssl.result b/mysql-test/r/ssl_mode_no_ssl.result
index 409b7a0fa1b..831bb3b71ab 100644
--- a/mysql-test/r/ssl_mode_no_ssl.result
+++ b/mysql-test/r/ssl_mode_no_ssl.result
@@ -1,22 +1,22 @@
# negative client tests
# mysql
-ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections
-ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections
-ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections
-ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections
+ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL
+ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL
+ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL
+ERROR 2026 (HY000): SSL connection error: Server doesn't support SSL
# mysqldump
-mysqldump: Got error: 2026: --ssl-mode=REQUIRED option forbids non SSL connections when trying to connect
+mysqldump: Got error: 2026: SSL connection error: Server doesn't support SSL when trying to connect
# mysqladmin
-mysqladmin: error: '--ssl-mode=REQUIRED option forbids non SSL connections'
+mysqladmin: error: 'SSL connection error: Server doesn't support SSL'
# mysqlcheck
-mysqlcheck: Got error: 2026: --ssl-mode=REQUIRED option forbids non SSL connections when trying to connect
+mysqlcheck: Got error: 2026: SSL connection error: Server doesn't support SSL when trying to connect
# mysqlimport
-mysqlimport: Error: 2026 --ssl-mode=REQUIRED option forbids non SSL connections
+mysqlimport: Error: 2026 SSL connection error: Server doesn't support SSL
# mysqlshow
-mysqlshow: --ssl-mode=REQUIRED option forbids non SSL connections
+mysqlshow: SSL connection error: Server doesn't support SSL
# mysqlslap
-mysqlslap: Error when connecting to server: --ssl-mode=REQUIRED option forbids non SSL connections
+mysqlslap: Error when connecting to server: SSL connection error: Server doesn't support SSL
# mysqltest
-mysqltest: Could not open connection 'default': 2026 --ssl-mode=REQUIRED option forbids non SSL connections
+mysqltest: Could not open connection 'default': 2026 SSL connection error: Server doesn't support SSL
End of tests
diff --git a/sql-common/client.c b/sql-common/client.c
index 3a6e205d384..759d95117cb 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1137,7 +1137,7 @@ static const char *default_options[]=
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
"multi-results", "multi-statements", "multi-queries", "secure-auth",
"report-data-truncation", "plugin-dir", "default-auth",
- "enable-cleartext-plugin",
+ "enable-cleartext-plugin", "ssl-mode",
NullS
};
enum option_id {
@@ -1149,7 +1149,7 @@ enum option_id {
OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name,
OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth,
OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth,
- OPT_enable_cleartext_plugin,
+ OPT_enable_cleartext_plugin, OPT_ssl_mode,
OPT_keep_this_one_last
};
@@ -1338,12 +1338,26 @@ void mysql_read_default_options(struct st_mysql_options *options,
my_free(options->ssl_cipher);
options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME));
break;
+ case OPT_ssl_mode:
+ if (opt_arg &&
+ !my_strcasecmp(&my_charset_latin1, opt_arg, "required"))
+ {
+ ENSURE_EXTENSIONS_PRESENT(options);
+ options->extension->ssl_mode= SSL_MODE_REQUIRED;
+ }
+ else
+ {
+ fprintf(stderr, "Unknown option to ssl-mode: %s\n", opt_arg);
+ exit(1);
+ }
+ break;
#else
case OPT_ssl_key:
case OPT_ssl_cert:
case OPT_ssl_ca:
case OPT_ssl_capath:
case OPT_ssl_cipher:
+ case OPT_ssl_mode:
break;
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
case OPT_character_sets_dir:
@@ -1850,6 +1864,10 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
mysql->options.ssl_capath = 0;
mysql->options.ssl_cipher= 0;
mysql->options.use_ssl = FALSE;
+ if (mysql->options.extension)
+ {
+ mysql->options.extension->ssl_mode= 0;
+ }
mysql->connector_fd = 0;
DBUG_VOID_RETURN;
}
@@ -2596,6 +2614,31 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
end= buff+5;
}
#ifdef HAVE_OPENSSL
+ /*
+ If SSL connection is required we'll:
+ 1. check if the server supports SSL;
+ 2. check if the client is properly configured;
+ 3. try to use SSL no matter the other options given.
+ */
+ if (mysql->options.extension &&
+ mysql->options.extension->ssl_mode == SSL_MODE_REQUIRED)
+ {
+ if (!(mysql->server_capabilities & CLIENT_SSL))
+ {
+ set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "Server doesn't support SSL");
+ goto error;
+ }
+ if (!mysql->options.use_ssl)
+ {
+ set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "Client is not configured to use SSL");
+ goto error;
+ }
+ mysql->client_flag|= CLIENT_SSL;
+ }
if (mysql->client_flag & CLIENT_SSL)
{
/* Do the SSL layering. */
@@ -4242,6 +4285,13 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
mysql->options.extension->enable_cleartext_plugin=
(*(my_bool*) arg) ? TRUE : FALSE;
break;
+ case MYSQL_OPT_SSL_MODE:
+ if (*(uint *) arg == SSL_MODE_REQUIRED)
+ {
+ ENSURE_EXTENSIONS_PRESENT(&mysql->options);
+ mysql->options.extension->ssl_mode= SSL_MODE_REQUIRED;
+ }
+ break;
default:
DBUG_RETURN(1);
}
From fc4c53c28899abf5547e0e0a89b4d91645250895 Mon Sep 17 00:00:00 2001
From: Karthik Kamath
Date: Fri, 10 Mar 2017 22:34:38 +0530
Subject: [PATCH 007/101] BUG#24807826: UINT3KORR SHOULD STOP READING FOUR
INSTEAD OF THREE BYTES ON X86
Post push fix for resolving main.archive test failure in valgrind.
---
sql/records.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sql/records.cc b/sql/records.cc
index ae7ec74c17d..14a4390b229 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -596,7 +596,7 @@ static int init_rr_cache(THD *thd, READ_RECORD *info)
DBUG_RETURN(1);
#ifdef HAVE_purify
// Avoid warnings in qsort
- bzero(info->cache,rec_cache_size+info->cache_records* info->struct_length+1);
+ bzero(info->cache,rec_cache_size+info->cache_records* info->struct_length);
#endif
DBUG_PRINT("info",("Allocated buffert for %d records",info->cache_records));
info->read_positions=info->cache+rec_cache_size;
From 8ea859d3007334065496b78dd8dd57e51c296a55 Mon Sep 17 00:00:00 2001
From: Ramil Kalimullin
Date: Mon, 13 Mar 2017 17:01:59 +0400
Subject: [PATCH 008/101] BUG#25575605: SETTING --SSL-MODE=REQUIRED SENDS
CREDENTIALS BEFORE VERIFYING SSL CONNECTION
Changed MYSQL_OPT_SSL_MODE to be the same as in 5.6 (ABI compatibility).
---
include/mysql.h | 4 +++-
include/mysql.h.pp | 3 ++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/include/mysql.h b/include/mysql.h
index 7ebf2f725a2..3a27ab4128c 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -167,7 +167,9 @@ enum mysql_option
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH,
- MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE
+ MYSQL_ENABLE_CLEARTEXT_PLUGIN,
+ /* Set MYSQL_OPT_SSL_MODE to be the same as in 5.6 (ABI compatibility). */
+ MYSQL_OPT_SSL_MODE= 38
};
/**
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index 0f292d921ee..774bf2d0301 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -263,7 +263,8 @@ enum mysql_option
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH,
- MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_SSL_MODE
+ MYSQL_ENABLE_CLEARTEXT_PLUGIN,
+ MYSQL_OPT_SSL_MODE= 38
};
struct st_mysql_options_extention;
struct st_mysql_options {
From d8328690d99aadad5c121da4eee05e940cddb8bb Mon Sep 17 00:00:00 2001
From: Kailasnath Nagarkar
Date: Wed, 15 Mar 2017 16:45:21 +0530
Subject: [PATCH 009/101] Bug #25447551: HANDLE_FATAL_SIGNAL (SIG=11) IN
FT_BOOLEAN_CHECK_SYNTAX_STRING
ISSUE: my_isalnum macro used for checking if character is
alphanumeric dereferences uninitialized pointer
in default character set structure resulting in
server exiting abnormally.
FIX: Used standard isalnum function instead of macro my_isalnum.
---
storage/myisam/ft_parser.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c
index 4d5899107c2..bbb85e8b68b 100644
--- a/storage/myisam/ft_parser.c
+++ b/storage/myisam/ft_parser.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,6 +16,7 @@
/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
#include "ftdefs.h"
+#include "ctype.h"
typedef struct st_ft_docstat {
FT_WORD *list;
@@ -89,7 +90,7 @@ my_bool ft_boolean_check_syntax_string(const uchar *str)
for (i=0; i 127 || my_isalnum(default_charset_info, str[i]))
+ if ((unsigned char)(str[i]) > 127 || isalnum(str[i]))
return 1;
for (j=0; j
Date: Fri, 17 Mar 2017 08:41:31 +0100
Subject: [PATCH 010/101] Bug #25717383: MYSQLDUMP MAY EXECUTE ANY ARBITRARY
QUERY
While writing comments if database object names has a new
line character, then next line is considered a command, rather
than a comment.
This patch fixes the way comments are constructed in mysqldump.
---
client/mysqldump.c | 54 +++++++++++++++++++++++-------
mysql-test/r/mysqldump.result | 63 +++++++++++++++++++++++++++++++++++
mysql-test/t/mysqldump.test | 50 +++++++++++++++++++++++++++
3 files changed, 155 insertions(+), 12 deletions(-)
diff --git a/client/mysqldump.c b/client/mysqldump.c
index fcd29e26fe3..2775769fe52 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -549,6 +549,7 @@ static int dump_tablespaces_for_databases(char** databases);
static int dump_tablespaces(char* ts_where);
static void print_comment(FILE *sql_file, my_bool is_error, const char *format,
...);
+static const char* fix_identifier_with_newline(char*);
/*
@@ -649,7 +650,7 @@ static void write_header(FILE *sql_file, char *db_name)
MACHINE_TYPE);
print_comment(sql_file, 0, "-- Host: %s Database: %s\n",
current_host ? current_host : "localhost",
- db_name ? db_name : "");
+ db_name ? fix_identifier_with_newline(db_name) : "");
print_comment(sql_file, 0,
"-- ------------------------------------------------------\n"
);
@@ -1981,6 +1982,30 @@ static void print_comment(FILE *sql_file, my_bool is_error, const char *format,
print_xml_comment(sql_file, strlen(comment_buff), comment_buff);
}
+/*
+ This function accepts object names and prefixes -- wherever \n
+ character is found.
+
+ @param[in] object_name
+
+ @return
+ @retval fixed object name.
+*/
+
+static const char* fix_identifier_with_newline(char* object_name)
+{
+ static char buff[COMMENT_LENGTH]= {0};
+ char *ptr= buff;
+ memset(buff, 0, 255);
+ while(*object_name)
+ {
+ *ptr++ = *object_name;
+ if (*object_name == '\n')
+ ptr= strmov(ptr, "-- ");
+ object_name++;
+ }
+ return buff;
+}
/*
create_delimiter
@@ -2049,7 +2074,8 @@ static uint dump_events_for_db(char *db)
/* nice comments */
print_comment(sql_file, 0,
- "\n--\n-- Dumping events for database '%s'\n--\n", db);
+ "\n--\n-- Dumping events for database '%s'\n--\n",
+ fix_identifier_with_newline(db));
/*
not using "mysql_query_with_error_report" because we may have not
@@ -2266,7 +2292,8 @@ static uint dump_routines_for_db(char *db)
/* nice comments */
print_comment(sql_file, 0,
- "\n--\n-- Dumping routines for database '%s'\n--\n", db);
+ "\n--\n-- Dumping routines for database '%s'\n--\n",
+ fix_identifier_with_newline(db));
/*
not using "mysql_query_with_error_report" because we may have not
@@ -2325,7 +2352,7 @@ static uint dump_routines_for_db(char *db)
query_buff);
print_comment(sql_file, 1,
"-- does %s have permissions on mysql.proc?\n\n",
- current_user);
+ fix_identifier_with_newline(current_user));
maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", current_user, query_buff);
}
else if (strlen(row[2]))
@@ -2539,11 +2566,11 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (strcmp (table_type, "VIEW") == 0) /* view */
print_comment(sql_file, 0,
"\n--\n-- Temporary table structure for view %s\n--\n\n",
- result_table);
+ fix_identifier_with_newline(result_table));
else
print_comment(sql_file, 0,
"\n--\n-- Table structure for table %s\n--\n\n",
- result_table);
+ fix_identifier_with_newline(result_table));
if (opt_drop)
{
@@ -2785,7 +2812,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
print_comment(sql_file, 0,
"\n--\n-- Table structure for table %s\n--\n\n",
- result_table);
+ fix_identifier_with_newline(result_table));
if (opt_drop)
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
if (!opt_xml)
@@ -3490,21 +3517,23 @@ static void dump_table(char *table, char *db)
{
print_comment(md_result_file, 0,
"\n--\n-- Dumping data for table %s\n--\n",
- result_table);
+ fix_identifier_with_newline(result_table));
dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM ");
dynstr_append_checked(&query_string, result_table);
if (where)
{
- print_comment(md_result_file, 0, "-- WHERE: %s\n", where);
+ print_comment(md_result_file, 0, "-- WHERE: %s\n",
+ fix_identifier_with_newline(where));
dynstr_append_checked(&query_string, " WHERE ");
dynstr_append_checked(&query_string, where);
}
if (order_by)
{
- print_comment(md_result_file, 0, "-- ORDER BY: %s\n", order_by);
+ print_comment(md_result_file, 0, "-- ORDER BY: %s\n",
+ fix_identifier_with_newline(order_by));
dynstr_append_checked(&query_string, " ORDER BY ");
dynstr_append_checked(&query_string, order_by);
@@ -4275,7 +4304,8 @@ static int init_dumping(char *database, int init_func(char*))
char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
print_comment(md_result_file, 0,
- "\n--\n-- Current Database: %s\n--\n", qdatabase);
+ "\n--\n-- Current Database: %s\n--\n",
+ fix_identifier_with_newline(qdatabase));
/* Call the view or table specific function */
init_func(qdatabase);
@@ -5281,7 +5311,7 @@ static my_bool get_view_structure(char *table, char* db)
print_comment(sql_file, 0,
"\n--\n-- Final view structure for view %s\n--\n\n",
- result_table);
+ fix_identifier_with_newline(result_table));
/* Table might not exist if this view was dumped with --tab. */
fprintf(sql_file, "/*!50001 DROP TABLE IF EXISTS %s*/;\n", opt_quoted_table);
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index c578f9e8df6..24746a3a51d 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -5283,3 +5283,66 @@ a
DROP TABLE t1;
DROP TABLE t2;
DROP DATABASE db_20772273;
+#
+# Bug #25717383: MYSQLDUMP MAY EXECUTE ANY ARBITRARY QUERY
+#
+CREATE DATABASE bug25717383;
+use bug25717383;
+CREATE TABLE `tab
+one` (a int);
+CREATE VIEW `view
+one` as SELECT * FROM `tab
+one`;
+CREATE PROCEDURE `proc
+one`() SELECT * from `tab
+one`;
+CREATE TEMPORARY TABLE `temp
+one` (id INT);
+CREATE TRIGGER `trig
+one` BEFORE INSERT ON `tab
+one` FOR EACH ROW SET NEW.a = 1;
+CREATE EVENT `event
+one` ON SCHEDULE AT '2030-01-01 00:00:00' DO SET @a=5;
+SHOW TABLES FROM bug25717383;
+Tables_in_bug25717383
+tab
+one
+view
+one
+SHOW TRIGGERS FROM bug25717383;
+Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
+trig
+one INSERT tab
+one SET NEW.a = 1 BEFORE NULL root@localhost utf8 utf8_general_ci latin1_swedish_ci
+SHOW EVENTS FROM bug25717383;
+Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
+bug25717383 event
+one root@localhost SYSTEM ONE TIME # NULL NULL NULL NULL ENABLED 1 utf8 utf8_general_ci latin1_swedish_ci
+SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES
+WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE'
+ ORDER BY ROUTINE_NAME;
+ROUTINE_NAME
+proc
+one
+SHOW TABLES FROM bug25717383;
+Tables_in_bug25717383
+tab
+one
+view
+one
+SHOW TRIGGERS FROM bug25717383;
+Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
+trig
+one INSERT tab
+one SET NEW.a = 1 BEFORE NULL root@localhost utf8 utf8_general_ci latin1_swedish_ci
+SHOW EVENTS FROM bug25717383;
+Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
+bug25717383 event
+one root@localhost SYSTEM ONE TIME # NULL NULL NULL NULL ENABLED 1 utf8 utf8_general_ci latin1_swedish_ci
+SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES
+WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE'
+ ORDER BY ROUTINE_NAME;
+ROUTINE_NAME
+proc
+one
+DROP DATABASE bug25717383;
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 11d766c3293..da958f83c48 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -2425,3 +2425,53 @@ SELECT * FROM t2;
DROP TABLE t1;
DROP TABLE t2;
DROP DATABASE db_20772273;
+
+--echo #
+--echo # Bug #25717383: MYSQLDUMP MAY EXECUTE ANY ARBITRARY QUERY
+--echo #
+
+
+CREATE DATABASE bug25717383;
+use bug25717383;
+
+CREATE TABLE `tab
+one` (a int);
+CREATE VIEW `view
+one` as SELECT * FROM `tab
+one`;
+
+CREATE PROCEDURE `proc
+one`() SELECT * from `tab
+one`;
+
+CREATE TEMPORARY TABLE `temp
+one` (id INT);
+
+CREATE TRIGGER `trig
+one` BEFORE INSERT ON `tab
+one` FOR EACH ROW SET NEW.a = 1;
+
+CREATE EVENT `event
+one` ON SCHEDULE AT '2030-01-01 00:00:00' DO SET @a=5;
+
+SHOW TABLES FROM bug25717383;
+SHOW TRIGGERS FROM bug25717383;
+--replace_column 6 #
+SHOW EVENTS FROM bug25717383;
+
+SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES
+ WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE'
+ ORDER BY ROUTINE_NAME;
+
+--exec $MYSQL_DUMP --triggers --events --routines --add-drop-database --databases bug25717383 > $MYSQLTEST_VARDIR/tmp/bug25717383.sql
+
+SHOW TABLES FROM bug25717383;
+SHOW TRIGGERS FROM bug25717383;
+--replace_column 6 #
+SHOW EVENTS FROM bug25717383;
+
+SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES
+ WHERE ROUTINE_SCHEMA='bug25717383' AND ROUTINE_TYPE= 'PROCEDURE'
+ ORDER BY ROUTINE_NAME;
+
+DROP DATABASE bug25717383;
From 741305b3a4a15b8957926f24300ea0b7da8d04bd Mon Sep 17 00:00:00 2001
From: "mysql-builder@oracle.com" <>
Date: Thu, 23 Mar 2017 22:57:25 +0530
Subject: [PATCH 011/101]
From 5d4cfb30e517e861defd9728e88f37ef6072becb Mon Sep 17 00:00:00 2001
From: Terje Rosten
Date: Tue, 28 Mar 2017 13:22:32 +0200
Subject: [PATCH 012/101] BUG#25719975 SHEBANG HARD CODED AS /USR/BIN/PERL IN
SCRIPTS, BREAKS ON FREEBSD
Use cmake variable to adjust shebang to platform.
---
scripts/CMakeLists.txt | 9 ++++++++-
scripts/dheadgen.pl | 8 +-------
scripts/mysql_config.pl.in | 4 ++--
scripts/mysql_convert_table_format.sh | 5 ++---
scripts/mysql_find_rows.sh | 5 ++---
scripts/mysql_fix_extensions.sh | 5 ++---
scripts/mysql_install_db.pl.in | 4 ++--
scripts/mysql_secure_installation.pl.in | 4 ++--
scripts/mysql_setpermission.sh | 5 ++---
scripts/mysql_zap.sh | 5 ++---
scripts/mysqlaccess.conf | 0
scripts/mysqlaccess.sh | 4 ++--
scripts/mysqld_multi.sh | 4 ++--
scripts/mysqldumpslow.sh | 5 ++---
scripts/mysqlhotcopy.sh | 4 ++--
15 files changed, 33 insertions(+), 38 deletions(-)
mode change 100755 => 100644 scripts/dheadgen.pl
mode change 100755 => 100644 scripts/mysql_secure_installation.pl.in
mode change 100755 => 100644 scripts/mysqlaccess.conf
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
index 920b6854334..d0fdf76ce9e 100644
--- a/scripts/CMakeLists.txt
+++ b/scripts/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -104,6 +104,13 @@ ELSE()
"${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
ENDIF()
+
+IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ SET (PERL_PATH "/usr/local/bin/perl")
+ELSE()
+ SET (PERL_PATH "/usr/bin/perl")
+ENDIF()
+
IF(UNIX)
# SHELL_PATH, FIND_PROC, CHECK_PID are used by mysqld_safe
IF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
diff --git a/scripts/dheadgen.pl b/scripts/dheadgen.pl
old mode 100755
new mode 100644
index c42bd49b32e..69ece2e7c81
--- a/scripts/dheadgen.pl
+++ b/scripts/dheadgen.pl
@@ -1,10 +1,4 @@
-#!/usr/bin/perl -w
-
-#
-# Copyright (c) 2008, 2009 Sun Microsystems, Inc.
-# Use is subject to license terms.
-#
-
+# Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
diff --git a/scripts/mysql_config.pl.in b/scripts/mysql_config.pl.in
index bced4a16360..edd258d5771 100644
--- a/scripts/mysql_config.pl.in
+++ b/scripts/mysql_config.pl.in
@@ -1,7 +1,7 @@
-#!/usr/bin/perl
+#!@PERL_PATH@
# -*- cperl -*-
#
-# Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/scripts/mysql_convert_table_format.sh b/scripts/mysql_convert_table_format.sh
index 2e5b5c11ab5..869a25c152b 100644
--- a/scripts/mysql_convert_table_format.sh
+++ b/scripts/mysql_convert_table_format.sh
@@ -1,6 +1,5 @@
-#!/usr/bin/perl
-# Copyright (c) 2000-2002, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc.
-# Use is subject to license terms.
+#!@PERL_PATH@
+# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/scripts/mysql_find_rows.sh b/scripts/mysql_find_rows.sh
index 48c4915ae00..20c3e2c3106 100644
--- a/scripts/mysql_find_rows.sh
+++ b/scripts/mysql_find_rows.sh
@@ -1,6 +1,5 @@
-#!/usr/bin/perl
-# Copyright (c) 2000, 2004, 2006 MySQL AB, 2009 Sun Microsystems, Inc.
-# Use is subject to license terms.
+#!@PERL_PATH@
+# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/scripts/mysql_fix_extensions.sh b/scripts/mysql_fix_extensions.sh
index 2a50bfe22bb..7aa07209d4d 100644
--- a/scripts/mysql_fix_extensions.sh
+++ b/scripts/mysql_fix_extensions.sh
@@ -1,7 +1,6 @@
-#!/usr/bin/perl
+#!@PERL_PATH@
-# Copyright (c) 2001 MySQL AB, 2009 Sun Microsystems, Inc.
-# Use is subject to license terms.
+# Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
diff --git a/scripts/mysql_install_db.pl.in b/scripts/mysql_install_db.pl.in
index 5f6bcabd518..760c7df887e 100644
--- a/scripts/mysql_install_db.pl.in
+++ b/scripts/mysql_install_db.pl.in
@@ -1,7 +1,7 @@
-#!/usr/bin/perl
+#!@PERL_PATH@
# -*- cperl -*-
#
-# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/scripts/mysql_secure_installation.pl.in b/scripts/mysql_secure_installation.pl.in
old mode 100755
new mode 100644
index 278fffe7322..09f2e20b6a3
--- a/scripts/mysql_secure_installation.pl.in
+++ b/scripts/mysql_secure_installation.pl.in
@@ -1,7 +1,7 @@
-#!/usr/bin/perl
+#!@PERL_PATH@
# -*- cperl -*-
#
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/scripts/mysql_setpermission.sh b/scripts/mysql_setpermission.sh
index 48f0b09b566..4416551eadd 100644
--- a/scripts/mysql_setpermission.sh
+++ b/scripts/mysql_setpermission.sh
@@ -1,8 +1,7 @@
-#!/usr/bin/perl
+#!@PERL_PATH@
## Emacs, this is -*- perl -*- mode? :-)
-# Copyright (c) 2000, 2007 MySQL AB, 2009 Sun Microsystems, Inc.
-# Use is subject to license terms.
+# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
diff --git a/scripts/mysql_zap.sh b/scripts/mysql_zap.sh
index a9c3e7a7f5a..725a4e247a4 100644
--- a/scripts/mysql_zap.sh
+++ b/scripts/mysql_zap.sh
@@ -1,6 +1,5 @@
-#!/usr/bin/perl
-# Copyright (c) 2000-2002, 2004, 2006 MySQL AB, 2009 Sun Microsystems, Inc.
-# Use is subject to license terms.
+#!@PERL_PATH@
+# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/scripts/mysqlaccess.conf b/scripts/mysqlaccess.conf
old mode 100755
new mode 100644
diff --git a/scripts/mysqlaccess.sh b/scripts/mysqlaccess.sh
index 4ca3b2d3686..03810e95b72 100644
--- a/scripts/mysqlaccess.sh
+++ b/scripts/mysqlaccess.sh
@@ -1,6 +1,6 @@
-#!/usr/bin/perl
+#!@PERL_PATH@
-# Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh
index d9ea6a117d2..a00704b6085 100644
--- a/scripts/mysqld_multi.sh
+++ b/scripts/mysqld_multi.sh
@@ -1,6 +1,6 @@
-#!/usr/bin/perl
+#!@PERL_PATH@
-# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
diff --git a/scripts/mysqldumpslow.sh b/scripts/mysqldumpslow.sh
index 94665f345f4..78040aac320 100644
--- a/scripts/mysqldumpslow.sh
+++ b/scripts/mysqldumpslow.sh
@@ -1,7 +1,6 @@
-#!/usr/bin/perl
+#!@PERL_PATH@
-# Copyright (c) 2000-2002, 2005-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
-# Use is subject to license terms.
+# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index a7f465dc891..2dc3a33c25d 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -1,6 +1,6 @@
-#!/usr/bin/perl
+#!@PERL_PATH@
-# Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
From 3c6c0ebc6a31835260d07463d581b9715776812f Mon Sep 17 00:00:00 2001
From: Nisha Gopalakrishnan
Date: Mon, 9 Jan 2017 20:09:57 +0530
Subject: [PATCH 013/101] BUG#25250768: WRITING ON A READ_ONLY=ON SERVER
WITHOUT SUPER PRIVILEGE.
Backport from mysql-5.7 to mysql-5.5 and mysql-5.6.
BUG#13969578: TEMPORARY TABLE IN A DATABASE ON A READ-ONLY
INSTANCE CAN BE OVERWRITTEN
Analysis:
========
Creation or modification of a persistent table by a non-super user
is NOT ALLOWED in read_only mode. Only TEMPORARY tables are allowed
to be created or modified in read_only mode. But the creation of
a persistent table was being allowed when a temporary table of
the same name existed.
The routine which denies updating a non-temporary table in a
read_only mode does not handle the case of creation of a regular
table when a temporary table of the same exists.
Fix:
===
Handled the condition where an attempt is made to create a persistent
table having the same name as that of the temporary table. Hence
the creation of a persistent table by a non-super user when a
temporary table of the same exists is denied under read_only mode.
---
sql/sql_parse.cc | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 86763b6e3de..82ab76b2e1c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -822,14 +822,18 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
(lex->sql_command == SQLCOM_CREATE_TABLE) &&
(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE);
+ const my_bool create_real_tables=
+ (lex->sql_command == SQLCOM_CREATE_TABLE) &&
+ !(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE);
+
const my_bool drop_temp_tables=
(lex->sql_command == SQLCOM_DROP_TABLE) &&
lex->drop_temporary;
const my_bool update_real_tables=
- some_non_temp_table_to_be_updated(thd, all_tables) &&
- !(create_temp_tables || drop_temp_tables);
-
+ ((create_real_tables ||
+ some_non_temp_table_to_be_updated(thd, all_tables)) &&
+ !(create_temp_tables || drop_temp_tables));
const my_bool create_or_drop_databases=
(lex->sql_command == SQLCOM_CREATE_DB) ||
From 07fb7b9c3d3ab403f110b6e52fa2d70e95bb6ded Mon Sep 17 00:00:00 2001
From: "mysql-builder@oracle.com" <>
Date: Mon, 10 Apr 2017 08:51:28 +0530
Subject: [PATCH 014/101]
From 788fb5bf678e2854fd2936cf6ac8d8f46f7c90c4 Mon Sep 17 00:00:00 2001
From: Shishir Jaiswal
Date: Mon, 17 Apr 2017 12:04:14 +0530
Subject: [PATCH 015/101] Bug#25043674 - MYSQLACCESS SCRIPT LOADS AND EXECUTES
CODE FROM THE CURRENT DIRECTORY
DESCRIPTION
===========
When 'mysqlaccess' tool is run, it reads (and executes) the
content of its configuration file 'mysqlaccess.conf' from
the current directory. This is not a recommended behaviour
as someone with ill intentions can insert malicious
instructions into this file which could be executed
whenever this tool is run.
ANALYSIS
========
The configuration file is presently looked for, in the
following folders (in given order):
1. Current directory
2. SYSCONFDIR //This gets expanded
3. /etc/
Owing to the reasons mentioned above, we should not permit
the file to be in the current directory. Since the other
two folders are assumed to be accessible only to authorized
people, the config file is safe to be read from there.
FIX
===
Modified the script so that it looks for the config file
now in the following two folders (in the given order):
1. SYSCONFDIR
2. /etc/
If it's absent from above locations but present in current
directory, an error is thrown asking the user to move the
file to one of the above locations and retry.
NOTE
====
The location paths and their precedence are not documented
for this tool. It needs to be noted as part of the
associated documentation.
---
mysql-test/mysql-test-run.pl | 13 ++++++++++++-
scripts/mysqlaccess.sh | 15 +++++++++++----
2 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 86d37a56835..2ca5c83e3f4 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -1,7 +1,7 @@
#!/usr/bin/perl
# -*- cperl -*-
-# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -2454,6 +2454,17 @@ sub environment_setup {
"$basedir/storage/myisam/myisampack",
"$basedir/myisam/myisampack"));
+ # ----------------------------------------------------
+ # mysqlaccess
+ # ----------------------------------------------------
+ my $mysqlaccess=
+ mtr_pl_maybe_exists("$bindir/scripts/mysqlaccess") ||
+ mtr_pl_maybe_exists("$path_client_bindir/mysqlaccess");
+ if ($mysqlaccess)
+ {
+ $ENV{'MYSQLACCESS'}= $mysqlaccess;
+ }
+
# ----------------------------------------------------
# mysqlhotcopy
# ----------------------------------------------------
diff --git a/scripts/mysqlaccess.sh b/scripts/mysqlaccess.sh
index 03810e95b72..85112a59ee4 100644
--- a/scripts/mysqlaccess.sh
+++ b/scripts/mysqlaccess.sh
@@ -477,15 +477,22 @@ MySQLaccess::Report::Print_Header();
# *****************************
# Read configuration-file
MySQLaccess::Debug::Print(1, "Reading configuration file...");
- if (-f "./$script_conf") {
- require "./$script_conf";
- }
- elsif (-f "@sysconfdir@/$script_conf") {
+ if (-f "@sysconfdir@/$script_conf") {
+ print "Configuration file '$script_conf' is found in '@sysconfdir@/'\n";
require "@sysconfdir@/$script_conf";
}
elsif (-f "/etc/$script_conf") {
+ print "Configuration file '$script_conf' is found in '/etc/'\n";
require "/etc/$script_conf";
}
+ elsif (-f "./$script_conf") {
+ print "\nERROR! Configuration file '$script_conf' is found in the current ";
+ print "directory.\nThe permissible locations for this file are either ";
+ print "@sysconfdir@/ or /etc/\n";
+ print "Please move it to one of these locations and retry.\n\n";
+ exit 0;
+ }
+
# ****************************
# Read in all parameters
From 8fab3ea01ff84b700d4686f9380c52cb30af7dc2 Mon Sep 17 00:00:00 2001
From: Balasubramanian Kandasamy
Date: Tue, 25 Apr 2017 13:12:30 +0530
Subject: [PATCH 016/101] Added plugins for commercial docker rpm builds
---
packaging/rpm-docker/mysql.spec.in | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/packaging/rpm-docker/mysql.spec.in b/packaging/rpm-docker/mysql.spec.in
index 5d35fb0a410..c5b7c664f59 100644
--- a/packaging/rpm-docker/mysql.spec.in
+++ b/packaging/rpm-docker/mysql.spec.in
@@ -1,4 +1,4 @@
-# Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -195,6 +195,9 @@ done
rm -f %{buildroot}%{_datadir}/mysql/{mysql.server,mysqld_multi.server,mysql-log-rotate,binary-configure}
rm -f %{buildroot}%{_datadir}/mysql/{*.ini,*.cnf}
+# Remove files pages we explicitly do not want to package
+rm -rf %{buildroot}%{_infodir}/mysql.info*
+
%check
%if 0%{?runselftest}
pushd release
@@ -271,6 +274,13 @@ rm -r $(readlink var) var
%attr(644, root, root) %{_datadir}/mysql/mysql_system_tables_data.sql
%attr(644, root, root) %{_datadir}/mysql/mysql_test_data_timezone.sql
%attr(644, root, root) %{_datadir}/mysql/magic
+
+%if 0%{?commercial}
+%attr(755, root, root) %{_libdir}/mysql/plugin/audit_log.so
+%attr(755, root, root) %{_libdir}/mysql/plugin/authentication_pam.so
+%attr(755, root, root) %{_libdir}/mysql/plugin/thread_pool.so
+%endif
+
%dir %attr(750, mysql, mysql) /var/lib/mysql
%dir %attr(755, mysql, mysql) /var/run/mysqld
%dir %attr(750, mysql, mysql) /var/lib/mysql-files
From c49b2707868d27c67e90c3844d570a97c573b9e5 Mon Sep 17 00:00:00 2001
From: Harin Vadodaria
Date: Thu, 27 Apr 2017 07:41:27 +0200
Subject: [PATCH 017/101] Bug#25942414: SSL VARIABLES USAGE WHEN LIBMYSQL IS
COMPILED WITH WITH_SSL=NO
Description: If libmysql is compiled with WITH_SSL=NO,
--ssl-* are not useful.
Solution: 1. Restricted WITH_SSL to values : bundled | yes | system
2. Made "bundled" as default value for WITH_SSL. Also,
not specifying WITH_SSL or even specifying WITH_SSL=no
will be treated as/converted to WITH_SSL=bundled.
Reviewed-By: Tor Didriksen
Reviewed-By: Georgi Kodinov
---
.../build_configurations/mysql_release.cmake | 4 +--
cmake/ssl.cmake | 27 +++++++++++--------
2 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake
index b0d3de10299..7d54e2aec77 100644
--- a/cmake/build_configurations/mysql_release.cmake
+++ b/cmake/build_configurations/mysql_release.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -169,7 +169,6 @@ IF(UNIX)
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "+O2 ${COMMON_CXX_FLAGS}")
ENDIF()
ENDIF()
- SET(WITH_SSL no)
ENDIF()
# Linux flags
@@ -185,7 +184,6 @@ IF(UNIX)
SET(CMAKE_CXX_FLAGS_DEBUG "${COMMON_CXX_FLAGS}")
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -unroll2 -ip ${COMMON_C_FLAGS}")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -unroll2 -ip ${COMMON_CXX_FLAGS}")
- SET(WITH_SSL no)
ENDIF()
ENDIF()
diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake
index 32b735410b7..f11c18a1bc8 100644
--- a/cmake/ssl.cmake
+++ b/cmake/ssl.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -11,10 +11,16 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+SET(WITH_SSL_DOC "bundled (use yassl)")
+SET(WITH_SSL_DOC
+ "${WITH_SSL_DOC}, yes (prefer os library if present, otherwise use bundled)")
+SET(WITH_SSL_DOC
+ "${WITH_SSL_DOC}, system (use os library)")
MACRO (CHANGE_SSL_SETTINGS string)
- SET(WITH_SSL ${string} CACHE STRING "Options are : no, bundled, yes (prefer os library if present otherwise use bundled), system (use os library)" FORCE)
+ SET(WITH_SSL ${string} CACHE STRING ${WITH_SSL_DOC} FORCE)
ENDMACRO()
MACRO (MYSQL_USE_BUNDLED_SSL)
@@ -50,14 +56,12 @@ ENDMACRO()
# MYSQL_CHECK_SSL
#
# Provides the following configure options:
-# WITH_SSL=[yes|no|bundled]
+# WITH_SSL=[bundled|yes|system]
MACRO (MYSQL_CHECK_SSL)
IF(NOT WITH_SSL)
- IF(WIN32)
CHANGE_SSL_SETTINGS("bundled")
- ELSE()
- CHANGE_SSL_SETTINGS("no")
- ENDIF()
+ MESSAGE(STATUS "Found WITH_SSL set to no. "
+ "Changing it to bundled")
ENDIF()
IF(WITH_SSL STREQUAL "bundled")
@@ -80,11 +84,12 @@ MACRO (MYSQL_CHECK_SSL)
CHANGE_SSL_SETTINGS("system")
ELSE()
IF(WITH_SSL STREQUAL "system")
- MESSAGE(SEND_ERROR "Cannot find appropriate system libraries for SSL. Use WITH_SSL=bundled to enable SSL support")
+ MESSAGE(SEND_ERROR "Cannot find appropriate system libraries for SSL. Use WITH_SSL=bundled to enable SSL support")
ENDIF()
MYSQL_USE_BUNDLED_SSL()
ENDIF()
- ELSEIF(NOT WITH_SSL STREQUAL "no")
- MESSAGE(SEND_ERROR "Wrong option for WITH_SSL. Valid values are : yes, no, bundled")
+ ELSE()
+ MESSAGE(SEND_ERROR "Wrong option for WITH_SSL. "
+ "Valid options are : ${WITH_SSL_DOC}")
ENDIF()
ENDMACRO()
From c230d3af1dec914580b9c0d9051725a0aa40fdf5 Mon Sep 17 00:00:00 2001
From: Balasubramanian Kandasamy
Date: Mon, 27 Feb 2017 17:20:51 +0530
Subject: [PATCH 018/101] Raise version number after cloning 5.5.55
(cherry picked from commit 7df8dc750c26ead87c643f87dccba28a66cf3c9b)
---
VERSION | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/VERSION b/VERSION
index bc0b19220b6..ade2e129c54 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
MYSQL_VERSION_MAJOR=5
MYSQL_VERSION_MINOR=5
-MYSQL_VERSION_PATCH=55
+MYSQL_VERSION_PATCH=56
MYSQL_VERSION_EXTRA=
From ad88f2a7b5c5827cb1ba78eee3497fb851b37a9f Mon Sep 17 00:00:00 2001
From: Harin Vadodaria
Date: Thu, 27 Apr 2017 07:41:27 +0200
Subject: [PATCH 019/101] Bug#25942414: SSL VARIABLES USAGE WHEN LIBMYSQL IS
COMPILED WITH WITH_SSL=NO
Description: If libmysql is compiled with WITH_SSL=NO,
--ssl-* are not useful.
Solution: 1. Restricted WITH_SSL to values : bundled | yes | system
2. Made "bundled" as default value for WITH_SSL. Also,
not specifying WITH_SSL or even specifying WITH_SSL=no
will be treated as/converted to WITH_SSL=bundled.
Reviewed-By: Tor Didriksen
Reviewed-By: Georgi Kodinov
(cherry picked from commit 3eb2058be34d1a21771fe89ff1a0c08f156899bc)
---
.../build_configurations/mysql_release.cmake | 4 +--
cmake/ssl.cmake | 27 +++++++++++--------
2 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake
index b0d3de10299..7d54e2aec77 100644
--- a/cmake/build_configurations/mysql_release.cmake
+++ b/cmake/build_configurations/mysql_release.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -169,7 +169,6 @@ IF(UNIX)
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "+O2 ${COMMON_CXX_FLAGS}")
ENDIF()
ENDIF()
- SET(WITH_SSL no)
ENDIF()
# Linux flags
@@ -185,7 +184,6 @@ IF(UNIX)
SET(CMAKE_CXX_FLAGS_DEBUG "${COMMON_CXX_FLAGS}")
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -unroll2 -ip ${COMMON_C_FLAGS}")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -unroll2 -ip ${COMMON_CXX_FLAGS}")
- SET(WITH_SSL no)
ENDIF()
ENDIF()
diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake
index 32b735410b7..f11c18a1bc8 100644
--- a/cmake/ssl.cmake
+++ b/cmake/ssl.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -11,10 +11,16 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+SET(WITH_SSL_DOC "bundled (use yassl)")
+SET(WITH_SSL_DOC
+ "${WITH_SSL_DOC}, yes (prefer os library if present, otherwise use bundled)")
+SET(WITH_SSL_DOC
+ "${WITH_SSL_DOC}, system (use os library)")
MACRO (CHANGE_SSL_SETTINGS string)
- SET(WITH_SSL ${string} CACHE STRING "Options are : no, bundled, yes (prefer os library if present otherwise use bundled), system (use os library)" FORCE)
+ SET(WITH_SSL ${string} CACHE STRING ${WITH_SSL_DOC} FORCE)
ENDMACRO()
MACRO (MYSQL_USE_BUNDLED_SSL)
@@ -50,14 +56,12 @@ ENDMACRO()
# MYSQL_CHECK_SSL
#
# Provides the following configure options:
-# WITH_SSL=[yes|no|bundled]
+# WITH_SSL=[bundled|yes|system]
MACRO (MYSQL_CHECK_SSL)
IF(NOT WITH_SSL)
- IF(WIN32)
CHANGE_SSL_SETTINGS("bundled")
- ELSE()
- CHANGE_SSL_SETTINGS("no")
- ENDIF()
+ MESSAGE(STATUS "Found WITH_SSL set to no. "
+ "Changing it to bundled")
ENDIF()
IF(WITH_SSL STREQUAL "bundled")
@@ -80,11 +84,12 @@ MACRO (MYSQL_CHECK_SSL)
CHANGE_SSL_SETTINGS("system")
ELSE()
IF(WITH_SSL STREQUAL "system")
- MESSAGE(SEND_ERROR "Cannot find appropriate system libraries for SSL. Use WITH_SSL=bundled to enable SSL support")
+ MESSAGE(SEND_ERROR "Cannot find appropriate system libraries for SSL. Use WITH_SSL=bundled to enable SSL support")
ENDIF()
MYSQL_USE_BUNDLED_SSL()
ENDIF()
- ELSEIF(NOT WITH_SSL STREQUAL "no")
- MESSAGE(SEND_ERROR "Wrong option for WITH_SSL. Valid values are : yes, no, bundled")
+ ELSE()
+ MESSAGE(SEND_ERROR "Wrong option for WITH_SSL. "
+ "Valid options are : ${WITH_SSL_DOC}")
ENDIF()
ENDMACRO()
From 80080eb389274ba69317a6c2019d5e8e23728b41 Mon Sep 17 00:00:00 2001
From: Balasubramanian Kandasamy
Date: Thu, 27 Apr 2017 12:27:52 +0530
Subject: [PATCH 020/101] Raise version number after cloning 5.5.56
---
VERSION | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/VERSION b/VERSION
index ade2e129c54..68358acf754 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
MYSQL_VERSION_MAJOR=5
MYSQL_VERSION_MINOR=5
-MYSQL_VERSION_PATCH=56
+MYSQL_VERSION_PATCH=57
MYSQL_VERSION_EXTRA=
From 756b00d80a46668d5a93ff927e13b5aea1c7d477 Mon Sep 17 00:00:00 2001
From: Anushree Prakash B
Date: Wed, 3 May 2017 15:16:08 +0000
Subject: [PATCH 021/101] Bug#25340722 - PRINT BINARY DATA AS HEX IN THE MYSQL
CLIENT (CONTRIBUTION)
DESCRIPTION:
============
Binary data should be printed as hex in the mysql client
when the option binary-as-hex is enabled.
ANALYSIS:
=========
The fix deals only with mysql command line client.
It does not change, at all, the data sent to the
applications. Printing binary data as hex also
allows to use the output in the where clause
of the query.
FIX:
====
A new option 'binary-as-hex' is introduced to print the
binary contents as hex in the mysql client. The option
is disabled by default. When the option is enabled, we
convert the binary data to hex before printing the
contents irrespective of whether it is in tabular,
xml or html format.
---
client/mysql.cc | 88 ++++++++++++++++++----
mysql-test/r/binary_to_hex.result | 117 ++++++++++++++++++++++++++++++
mysql-test/t/binary_to_hex.test | 76 +++++++++++++++++++
3 files changed, 268 insertions(+), 13 deletions(-)
create mode 100644 mysql-test/r/binary_to_hex.result
create mode 100644 mysql-test/t/binary_to_hex.test
diff --git a/client/mysql.cc b/client/mysql.cc
index 2269563814c..6e6dc4971ac 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -142,7 +142,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
default_pager_set= 0, opt_sigint_ignore= 0,
auto_vertical_output= 0,
show_warnings= 0, executing_query= 0, interrupted_query= 0,
- ignore_spaces= 0;
+ ignore_spaces= 0, opt_binhex= 0;
static my_bool debug_info_flag, debug_check_flag;
static my_bool column_types_flag;
static my_bool preserve_comments= 0;
@@ -1392,6 +1392,8 @@ static struct my_option my_long_options[] =
{"batch", 'B',
"Don't use history file. Disable interactive behavior. (Enables --silent.)",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"binary-as-hex", 'b', "Print binary data as hex", &opt_binhex, &opt_binhex,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
"Directory for character set files.", &charsets_dir,
&charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -3101,7 +3103,8 @@ com_go(String *buffer,char *line __attribute__((unused)))
print_table_data_html(result);
else if (opt_xml)
print_table_data_xml(result);
- else if (vertical || (auto_vertical_output && (terminal_width < get_result_width(result))))
+ else if (vertical || (auto_vertical_output &&
+ (terminal_width < get_result_width(result))))
print_table_data_vertically(result);
else if (opt_silent && verbose <= 2 && !output_tables)
print_tab_data(result);
@@ -3320,6 +3323,41 @@ print_field_types(MYSQL_RES *result)
}
+/* Used to determine if we should invoke print_as_hex for this field */
+
+static bool
+is_binary_field(MYSQL_FIELD *field)
+{
+ if ((field->charsetnr == 63) &&
+ (field->type == MYSQL_TYPE_BIT ||
+ field->type == MYSQL_TYPE_BLOB ||
+ field->type == MYSQL_TYPE_LONG_BLOB ||
+ field->type == MYSQL_TYPE_MEDIUM_BLOB ||
+ field->type == MYSQL_TYPE_TINY_BLOB ||
+ field->type == MYSQL_TYPE_VAR_STRING ||
+ field->type == MYSQL_TYPE_STRING ||
+ field->type == MYSQL_TYPE_VARCHAR ||
+ field->type == MYSQL_TYPE_GEOMETRY))
+ return 1;
+ return 0;
+}
+
+
+/* Print binary value as hex literal (0x ...) */
+
+static void
+print_as_hex(FILE *output_file, const char *str, ulong len, ulong total_bytes_to_send)
+{
+ const char *ptr= str, *end= ptr+len;
+ ulong i;
+ fprintf(output_file, "0x");
+ for(; ptr < end; ptr++)
+ fprintf(output_file, "%02X", *((uchar*)ptr));
+ for (i= 2*len+2; i < total_bytes_to_send; i++)
+ tee_putc((int)' ', output_file);
+}
+
+
static void
print_table_data(MYSQL_RES *result)
{
@@ -3346,6 +3384,8 @@ print_table_data(MYSQL_RES *result)
length=max(length,field->max_length);
if (length < 4 && !IS_NOT_NULL(field->flags))
length=4; // Room for "NULL"
+ if (opt_binhex && is_binary_field(field))
+ length= 2 + length * 2;
field->max_length=length;
separator.fill(separator.length()+length+2,'-');
separator.append('+');
@@ -3415,7 +3455,9 @@ print_table_data(MYSQL_RES *result)
visible_length= charset_info->cset->numcells(charset_info, buffer, buffer + data_length);
extra_padding= data_length - visible_length;
- if (field_max_length > MAX_COLUMN_LENGTH)
+ if (opt_binhex && is_binary_field(field))
+ print_as_hex(PAGER, cur[off], lengths[off], field_max_length);
+ else if (field_max_length > MAX_COLUMN_LENGTH)
tee_print_sized_data(buffer, data_length, MAX_COLUMN_LENGTH+extra_padding, FALSE);
else
{
@@ -3548,11 +3590,15 @@ print_table_data_html(MYSQL_RES *result)
if (interrupted_query)
break;
ulong *lengths=mysql_fetch_lengths(result);
+ field= mysql_fetch_fields(result);
(void) tee_fputs("", PAGER);
for (uint i=0; i < mysql_num_fields(result); i++)
{
(void) tee_fputs("", PAGER);
- xmlencode_print(cur[i], lengths[i]);
+ if (opt_binhex && is_binary_field(&field[i]))
+ print_as_hex(PAGER, cur[i], lengths[i], lengths[i]);
+ else
+ xmlencode_print(cur[i], lengths[i]);
(void) tee_fputs(" | ", PAGER);
}
(void) tee_fputs("
", PAGER);
@@ -3588,7 +3634,10 @@ print_table_data_xml(MYSQL_RES *result)
if (cur[i])
{
tee_fprintf(PAGER, "\">");
- xmlencode_print(cur[i], lengths[i]);
+ if (opt_binhex && is_binary_field(&fields[i]))
+ print_as_hex(PAGER, cur[i], lengths[i], lengths[i]);
+ else
+ xmlencode_print(cur[i], lengths[i]);
tee_fprintf(PAGER, "\n");
}
else
@@ -3635,23 +3684,28 @@ print_table_data_vertically(MYSQL_RES *result)
{
unsigned int i;
const char *p;
-
+ if (opt_binhex && is_binary_field(field))
+ fprintf(PAGER, "0x");
for (i= 0, p= cur[off]; i < lengths[off]; i+= 1, p+= 1)
{
- if (*p == '\0')
- tee_putc((int)' ', PAGER);
+ if (opt_binhex && is_binary_field(field))
+ fprintf(PAGER, "%02X", *((uchar*)p));
else
- tee_putc((int)*p, PAGER);
+ {
+ if (*p == '\0')
+ tee_putc((int)' ', PAGER);
+ else
+ tee_putc((int)*p, PAGER);
+ }
}
tee_putc('\n', PAGER);
}
- else
+ else
tee_fprintf(PAGER, "NULL\n");
}
}
}
-
/* print_warnings should be called right after executing a statement */
static void print_warnings()
@@ -3788,11 +3842,19 @@ print_tab_data(MYSQL_RES *result)
while ((cur = mysql_fetch_row(result)))
{
lengths=mysql_fetch_lengths(result);
- safe_put_field(cur[0],lengths[0]);
+ field= mysql_fetch_fields(result);
+ if (opt_binhex && is_binary_field(&field[0]))
+ print_as_hex(PAGER, cur[0], lengths[0], lengths[0]);
+ else
+ safe_put_field(cur[0],lengths[0]);
+
for (uint off=1 ; off < mysql_num_fields(result); off++)
{
(void) tee_fputs("\t", PAGER);
- safe_put_field(cur[off], lengths[off]);
+ if (opt_binhex && field && is_binary_field(&field[off]))
+ print_as_hex(PAGER, cur[off], lengths[off], lengths[off]);
+ else
+ safe_put_field(cur[off], lengths[off]);
}
(void) tee_fputs("\n", PAGER);
}
diff --git a/mysql-test/r/binary_to_hex.result b/mysql-test/r/binary_to_hex.result
new file mode 100644
index 00000000000..a6b68834da8
--- /dev/null
+++ b/mysql-test/r/binary_to_hex.result
@@ -0,0 +1,117 @@
+USE test;
+DROP TABLE IF EXISTS t1, t2;
+CREATE TABLE t1 (c1 TINYBLOB,
+c2 BLOB,
+c3 MEDIUMBLOB,
+c4 LONGBLOB,
+c5 TEXT,
+c6 BIT(1),
+c7 CHAR,
+c8 VARCHAR(10),
+c9 GEOMETRY) CHARACTER SET = binary;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` tinyblob,
+ `c2` blob,
+ `c3` mediumblob,
+ `c4` longblob,
+ `c5` blob,
+ `c6` bit(1) DEFAULT NULL,
+ `c7` binary(1) DEFAULT NULL,
+ `c8` varbinary(10) DEFAULT NULL,
+ `c9` geometry DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=binary
+INSERT INTO t1 VALUES ('tinyblob-text readable', 'blob-text readable',
+'mediumblob-text readable', 'longblob-text readable',
+'text readable', b'1', 'c', 'variable',
+POINT(1, 1));
+CREATE TABLE t2(id int, `col1` binary(10),`col2` blob);
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) DEFAULT NULL,
+ `col1` binary(10) DEFAULT NULL,
+ `col2` blob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+INSERT INTO t2 VALUES (1, X'AB1234', X'123ABC'), (2, X'DE1234', X'123DEF');
+#Print the table contents when binary-as-hex option is off.
+SELECT * FROM t1;
+c1 c2 c3 c4 c5 c6 c7 c8 c9
+tinyblob-text readable blob-text readable mediumblob-text readable longblob-text readable text readable # c variable #
+SELECT * FROM t2;
+id col1 col2
+1 # #
+2 # #
+#Print the table contents after turning on the binary-as-hex option
+
+#Print the table contents in tab format
+
+c1 c2 c3 c4 c5 c6 c7 c8 c9
+0x74696E79626C6F622D74657874207265616461626C65 0x626C6F622D74657874207265616461626C65 0x6D656469756D626C6F622D74657874207265616461626C65 0x6C6F6E67626C6F622D74657874207265616461626C65 0x74657874207265616461626C65 0x01 0x63 0x7661726961626C65 0x000000000101000000000000000000F03F000000000000F03F
+id col1 col2
+1 0xAB123400000000000000 0x123ABC
+2 0xDE123400000000000000 0x123DEF
+
+#Print the table contents in table format
+
++------------------------------------------------+----------------------------------------+----------------------------------------------------+------------------------------------------------+------------------------------+------------+------------+--------------------+------------------------------------------------------+
+| c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 |
++------------------------------------------------+----------------------------------------+----------------------------------------------------+------------------------------------------------+------------------------------+------------+------------+--------------------+------------------------------------------------------+
+| 0x74696E79626C6F622D74657874207265616461626C65 | 0x626C6F622D74657874207265616461626C65 | 0x6D656469756D626C6F622D74657874207265616461626C65 | 0x6C6F6E67626C6F622D74657874207265616461626C65 | 0x74657874207265616461626C65 | 0x01 | 0x63 | 0x7661726961626C65 | 0x000000000101000000000000000000F03F000000000000F03F |
++------------------------------------------------+----------------------------------------+----------------------------------------------------+------------------------------------------------+------------------------------+------------+------------+--------------------+------------------------------------------------------+
++------+------------------------+------------+
+| id | col1 | col2 |
++------+------------------------+------------+
+| 1 | 0xAB123400000000000000 | 0x123ABC |
++------+------------------------+------------+
+
+#Print the table contents vertically
+
+*************************** 1. row ***************************
+c1: 0x74696E79626C6F622D74657874207265616461626C65
+c2: 0x626C6F622D74657874207265616461626C65
+c3: 0x6D656469756D626C6F622D74657874207265616461626C65
+c4: 0x6C6F6E67626C6F622D74657874207265616461626C65
+c5: 0x74657874207265616461626C65
+c6: 0x01
+c7: 0x63
+c8: 0x7661726961626C65
+c9: 0x000000000101000000000000000000F03F000000000000F03F
+
+#Print the table contents in xml format
+
+
+
+
+
+ 0x74696E79626C6F622D74657874207265616461626C65
+ 0x626C6F622D74657874207265616461626C65
+ 0x6D656469756D626C6F622D74657874207265616461626C65
+ 0x6C6F6E67626C6F622D74657874207265616461626C65
+ 0x74657874207265616461626C65
+ 0x01
+ 0x63
+ 0x7661726961626C65
+ 0x000000000101000000000000000000F03F000000000000F03F
+
+
+
+
+
+
+ 1
+ 0xAB123400000000000000
+ 0x123ABC
+
+
+
+ 2
+ 0xDE123400000000000000
+ 0x123DEF
+
+
+
+#Print the table contents in html format
+
+c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 |
---|
0x74696E79626C6F622D74657874207265616461626C65 | 0x626C6F622D74657874207265616461626C65 | 0x6D656469756D626C6F622D74657874207265616461626C65 | 0x6C6F6E67626C6F622D74657874207265616461626C65 | 0x74657874207265616461626C65 | 0x01 | 0x63 | 0x7661726961626C65 | 0x000000000101000000000000000000F03F000000000000F03F |
id | col1 | col2 |
---|
1 | 0xAB123400000000000000 | 0x123ABC |
2 | 0xDE123400000000000000 | 0x123DEF |
DROP TABLE t1, t2;
diff --git a/mysql-test/t/binary_to_hex.test b/mysql-test/t/binary_to_hex.test
new file mode 100644
index 00000000000..8312a246d0c
--- /dev/null
+++ b/mysql-test/t/binary_to_hex.test
@@ -0,0 +1,76 @@
+# === Purpose ===
+# The purpose of this test case is to make
+# sure that the binary data in tables is printed
+# as hex when the option binary-as-hex is enabled.
+#
+# === Related bugs and/or worklogs ===
+# Bug #25340722 - PRINT BINARY DATA AS HEX IN THE MYSQL
+# CLIENT (CONTRIBUTION)
+#
+
+# Save the initial number of concurrent sessions
+--source include/count_sessions.inc
+--source include/not_embedded.inc
+
+USE test;
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+--enable_warnings
+
+CREATE TABLE t1 (c1 TINYBLOB,
+ c2 BLOB,
+ c3 MEDIUMBLOB,
+ c4 LONGBLOB,
+ c5 TEXT,
+ c6 BIT(1),
+ c7 CHAR,
+ c8 VARCHAR(10),
+ c9 GEOMETRY) CHARACTER SET = binary;
+
+SHOW CREATE TABLE t1;
+
+INSERT INTO t1 VALUES ('tinyblob-text readable', 'blob-text readable',
+ 'mediumblob-text readable', 'longblob-text readable',
+ 'text readable', b'1', 'c', 'variable',
+ POINT(1, 1));
+
+CREATE TABLE t2(id int, `col1` binary(10),`col2` blob);
+
+SHOW CREATE TABLE t2;
+
+INSERT INTO t2 VALUES (1, X'AB1234', X'123ABC'), (2, X'DE1234', X'123DEF');
+
+--echo #Print the table contents when binary-as-hex option is off.
+--replace_column 6 # 9 #
+SELECT * FROM t1;
+
+--replace_column 2 # 3 #
+SELECT * FROM t2;
+
+--echo #Print the table contents after turning on the binary-as-hex option
+--echo
+--echo #Print the table contents in tab format
+--echo
+--exec $MYSQL test --binary-as-hex -e "SELECT * FROM t1; SELECT * FROM t2;"
+--echo
+--echo #Print the table contents in table format
+--echo
+--exec $MYSQL test --binary-as-hex --table -e "SELECT * FROM t1; SELECT * FROM t2 WHERE col2=0x123ABC;"
+--echo
+--echo #Print the table contents vertically
+--echo
+--exec $MYSQL test --binary-as-hex --vertical -e "SELECT * FROM t1;"
+--echo
+--echo #Print the table contents in xml format
+--echo
+--exec $MYSQL test --binary-as-hex --xml -e "SELECT * FROM t1; SELECT * FROM t2;"
+--echo
+--echo #Print the table contents in html format
+--echo
+--exec $MYSQL test --binary-as-hex --html -e "SELECT * FROM t1; SELECT * FROM t2;"
+
+#Cleanup
+DROP TABLE t1, t2;
+
+# Wait till all disconnects are completed
+ --source include/wait_until_count_sessions.inc
From 67bec60c726ee25e5c4a82709397c65c4e768e3e Mon Sep 17 00:00:00 2001
From: Balasubramanian Kandasamy
Date: Thu, 4 May 2017 16:05:04 +0530
Subject: [PATCH 022/101] Bug#25998285 - ADD MYSQLADMIN DOCKER/MINIMAL SERVER
BUILDS
- mysqladmin is needed by InnoDB Cluster, add tool to docker/minimal package.
---
packaging/rpm-docker/mysql.spec.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packaging/rpm-docker/mysql.spec.in b/packaging/rpm-docker/mysql.spec.in
index c5b7c664f59..497ae395577 100644
--- a/packaging/rpm-docker/mysql.spec.in
+++ b/packaging/rpm-docker/mysql.spec.in
@@ -177,7 +177,7 @@ for f in msql2mysql mysqlaccess mysqlaccess.conf mysqlbug mysql_convert_table_fo
rm -f %{buildroot}%{_bindir}/$f
done
-for f in innochecksum myisamchk myisam_ftdump myisamlog myisampack mysqladmin \
+for f in innochecksum myisamchk myisam_ftdump myisamlog myisampack \
mysqlbinlog mysqlcheck mysql_client_test mysql_config_editor \
mysqld_multi mysqld_safe mysqldumpslow mysql_embedded mysqlimport \
mysql_plugin mysql_secure_installation mysqlshow mysqlslap mysqltest \
@@ -231,6 +231,7 @@ rm -r $(readlink var) var
%dir %{_sysconfdir}/my.cnf.d
%attr(755, root, root) %{_sbindir}/mysqld
%attr(755, root, root) %{_bindir}/mysql
+%attr(755, root, root) %{_bindir}/mysqladmin
%attr(755, root, root) %{_bindir}/mysqldump
%attr(755, root, root) %{_bindir}/mysql_config
%attr(755, root, root) %{_bindir}/mysql_install_db
From b615c3dff885b1ce44fa2275aec8f04c8963ea75 Mon Sep 17 00:00:00 2001
From: Nisha Gopalakrishnan
Date: Fri, 12 May 2017 09:47:48 +0530
Subject: [PATCH 023/101] BUG#25451091:CREATE TABLE DATA DIRECTORY / INDEX
DIRECTORY SYMLINK CHECK RACE CONDITIONS
ANALYSIS:
=========
A potential defect exists in the handling of CREATE
TABLE .. DATA DIRECTORY/ INDEX DIRECTORY which gives way to
the user to gain access to another user table or a system
table.
FIX:
====
The lstat and fstat output of the target files are now
stored which help in determining the identity of the target
files thus preventing the unauthorized access to other
files.
---
include/my_sys.h | 16 ++++++++--
mysys/my_symlink.c | 30 +++++++++++++++++--
storage/myisam/mi_delete_table.c | 6 ++--
storage/myisam/mi_open.c | 50 +++++++++++++++++++++++++-------
4 files changed, 83 insertions(+), 19 deletions(-)
diff --git a/include/my_sys.h b/include/my_sys.h
index 472c2ba5ca0..9983ee3319f 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -49,6 +49,7 @@ typedef struct my_aio_result {
#ifdef _WIN32
#include /*for alloca*/
#endif
+#include
#define MY_INIT(name) { my_progname= name; my_init(); }
@@ -491,6 +492,16 @@ typedef struct st_io_cache /* Used when cacheing files */
typedef int (*qsort2_cmp)(const void *, const void *, const void *);
+/*
+ Subset of struct stat fields filled by stat/lstat/fstat that uniquely
+ identify a file
+*/
+typedef struct st_file_id
+{
+ dev_t st_dev;
+ ino_t st_ino;
+} ST_FILE_ID;
+
/* defines for mf_iocache */
/* Test if buffer is inited */
@@ -569,8 +580,9 @@ extern File my_create(const char *FileName,int CreateFlags,
extern int my_close(File Filedes,myf MyFlags);
extern int my_mkdir(const char *dir, int Flags, myf MyFlags);
extern int my_readlink(char *to, const char *filename, myf MyFlags);
-extern int my_is_symlink(const char *filename);
+extern int my_is_symlink(const char *filename, ST_FILE_ID *file_id);
extern int my_realpath(char *to, const char *filename, myf MyFlags);
+extern int my_is_same_file(File file, const ST_FILE_ID *file_id);
extern File my_create_with_symlink(const char *linkname, const char *filename,
int createflags, int access_flags,
myf MyFlags);
diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c
index cdb16a7422b..4569fcf7fbf 100644
--- a/mysys/my_symlink.c
+++ b/mysys/my_symlink.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -99,11 +99,18 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags)
#endif
-int my_is_symlink(const char *filename __attribute__((unused)))
+int my_is_symlink(const char *filename __attribute__((unused)),
+ ST_FILE_ID *file_id)
{
#if defined (HAVE_LSTAT) && defined (S_ISLNK)
struct stat stat_buff;
- return !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode);
+ int result= !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode);
+ if (file_id && !result)
+ {
+ file_id->st_dev= stat_buff.st_dev;
+ file_id->st_ino= stat_buff.st_ino;
+ }
+ return result;
#elif defined (_WIN32)
DWORD dwAttr = GetFileAttributes(filename);
return (dwAttr != INVALID_FILE_ATTRIBUTES) &&
@@ -164,3 +171,20 @@ int my_realpath(char *to, const char *filename, myf MyFlags)
#endif
return 0;
}
+
+
+/**
+ Return non-zero if the file descriptor and a previously lstat-ed file
+ identified by file_id point to the same file
+*/
+int my_is_same_file(File file, const ST_FILE_ID *file_id)
+{
+ MY_STAT stat_buf;
+ if (my_fstat(file, &stat_buf, MYF(0)) == -1)
+ {
+ my_errno= errno;
+ return 0;
+ }
+ return (stat_buf.st_dev == file_id->st_dev)
+ && (stat_buf.st_ino == file_id->st_ino);
+}
diff --git a/storage/myisam/mi_delete_table.c b/storage/myisam/mi_delete_table.c
index b6530334dd2..768b4618928 100644
--- a/storage/myisam/mi_delete_table.c
+++ b/storage/myisam/mi_delete_table.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -29,7 +29,7 @@ int mi_delete_table(const char *name)
#endif
fn_format(from,name,"",MI_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
- if (my_is_symlink(from) && (*myisam_test_invalid_symlink)(from))
+ if (my_is_symlink(from, NULL) && (*myisam_test_invalid_symlink)(from))
{
/*
Symlink is pointing to file in data directory.
@@ -44,7 +44,7 @@ int mi_delete_table(const char *name)
DBUG_RETURN(my_errno);
}
fn_format(from,name,"",MI_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
- if (my_is_symlink(from) && (*myisam_test_invalid_symlink)(from))
+ if (my_is_symlink(from, NULL) && (*myisam_test_invalid_symlink)(from))
{
/*
Symlink is pointing to file in data directory.
diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c
index 93f70a5d340..1f0cc8e2169 100644
--- a/storage/myisam/mi_open.c
+++ b/storage/myisam/mi_open.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -78,6 +78,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
ulonglong max_key_file_length, max_data_file_length;
+ ST_FILE_ID file_id= {0, 0};
DBUG_ENTER("mi_open");
LINT_INIT(m_info);
@@ -89,11 +90,15 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
realpath_err= my_realpath(name_buff,
fn_format(org_name,name,"",MI_NAME_IEXT,4),MYF(0));
- if (my_is_symlink(org_name) &&
- (realpath_err || (*myisam_test_invalid_symlink)(name_buff)))
+ if (my_is_symlink(name_buff, &file_id))
{
- my_errno= HA_WRONG_CREATE_OPTION;
- DBUG_RETURN (NULL);
+ if (realpath_err ||
+ (*myisam_test_invalid_symlink)(name_buff) ||
+ my_is_symlink(name_buff, &file_id))
+ {
+ my_errno= HA_WRONG_CREATE_OPTION;
+ DBUG_RETURN (NULL);
+ }
}
mysql_mutex_lock(&THR_LOCK_myisam);
@@ -113,17 +118,28 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
my_errno= HA_ERR_CRASHED;
goto err;
});
+ DEBUG_SYNC_C("before_opening_indexfile");
if ((kfile= mysql_file_open(mi_key_file_kfile,
name_buff,
- (open_mode= O_RDWR) | O_SHARE, MYF(0))) < 0)
+ (open_mode= O_RDWR) | O_SHARE | O_NOFOLLOW,
+ MYF(0))) < 0)
{
if ((errno != EROFS && errno != EACCES) ||
mode != O_RDONLY ||
(kfile= mysql_file_open(mi_key_file_kfile,
name_buff,
- (open_mode= O_RDONLY) | O_SHARE, MYF(0))) < 0)
+ (open_mode= O_RDONLY) | O_SHARE | O_NOFOLLOW,
+ MYF(0))) < 0)
goto err;
}
+
+ if (!my_is_same_file(kfile, &file_id))
+ {
+ mysql_file_close(kfile, MYF(0));
+ my_errno= HA_WRONG_CREATE_OPTION;
+ goto err;
+ }
+
share->mode=open_mode;
errpos=1;
if (mysql_file_read(kfile, share->state.header.file_version, head_length,
@@ -1206,14 +1222,16 @@ int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *org_name,
{
char *data_name= share->data_file_name;
char real_data_name[FN_REFLEN];
+ ST_FILE_ID file_id= {0, 0};
if (org_name)
{
fn_format(real_data_name,org_name,"",MI_NAME_DEXT,4);
- if (my_is_symlink(real_data_name))
+ if (my_is_symlink(real_data_name, &file_id))
{
if (my_realpath(real_data_name, real_data_name, MYF(0)) ||
- (*myisam_test_invalid_symlink)(real_data_name))
+ (*myisam_test_invalid_symlink)(real_data_name) ||
+ my_is_symlink(real_data_name, &file_id))
{
my_errno= HA_WRONG_CREATE_OPTION;
return 1;
@@ -1221,9 +1239,19 @@ int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *org_name,
data_name= real_data_name;
}
}
+ DEBUG_SYNC_C("before_opening_datafile");
info->dfile= mysql_file_open(mi_key_file_dfile,
- data_name, share->mode | O_SHARE, MYF(MY_WME));
- return info->dfile >= 0 ? 0 : 1;
+ data_name, share->mode | O_SHARE | O_NOFOLLOW,
+ MYF(MY_WME));
+ if (info->dfile < 0)
+ return 1;
+ if (org_name && !my_is_same_file(info->dfile, &file_id))
+ {
+ mysql_file_close(info->dfile, MYF(0));
+ my_errno= HA_WRONG_CREATE_OPTION;
+ return 1;
+ }
+ return 0;
}
From af676805109135fba189410e90cd753ff4fc22b5 Mon Sep 17 00:00:00 2001
From: "mysql-builder@oracle.com" <>
Date: Sat, 13 May 2017 10:22:46 +0530
Subject: [PATCH 024/101]
From f4ce18b0a6954c01579698d2865e5c3aa8763df7 Mon Sep 17 00:00:00 2001
From: Tor Didriksen
Date: Wed, 26 Apr 2017 12:45:38 +0200
Subject: [PATCH 025/101] Bug #25436469: BUILDS ARE NOT REPRODUCIBLE
Backport to 5.5
Current MySQL builds, even on Pushbuild, are not reproducible; they return
different results depending on which directory they are built from (and
Pushbuild uses several different directories). This is because absolute paths
leak into debug information, and even worse, __FILE__. The latter moves code
around enough that we've actually seen sysbench changes on the order of 4% in
some tests.
CMake seemingly insists on using absolute paths, but we can insert our own
layer between CMake and GCC to relativize all paths. Also give the right flags
to get debug information reproducible and turn off build stamping. This makes
the mysqld build 100% bit-for-bit reproducible between runs on my machine,
even when run from different directories.
---
CMakeLists.txt | 30 +++++++++
scripts/invoke-with-relative-paths.pl | 95 +++++++++++++++++++++++++++
2 files changed, 125 insertions(+)
create mode 100755 scripts/invoke-with-relative-paths.pl
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ba5e60f6146..154273576d7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -263,6 +263,36 @@ IF (ENABLE_GCOV AND NOT WIN32 AND NOT APPLE)
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage -lgcov")
ENDIF()
+IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+ OPTION(REPRODUCIBLE_BUILD "Take extra pains to make build result independent of build location and time" OFF)
+ENDIF()
+IF(REPRODUCIBLE_BUILD)
+ SET(DEBUG_PREFIX_FLAGS
+ "-fdebug-prefix-map=${CMAKE_SOURCE_DIR}/=./ -fdebug-prefix-map=${CMAKE_CURRENT_BINARY_DIR}=./obj")
+
+ # See if -fdebug-prefix= commands are included in the debug output,
+ # making the build unreproducible with switches recorded.
+ # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69821.
+ EXECUTE_PROCESS(COMMAND ${CMAKE_C_COMPILER} -g3 -x c -S -fdebug-prefix-map=foo=bar -o - -
+ INPUT_FILE /dev/null OUTPUT_VARIABLE DEBUG_PREFIX_MAP_RESULT)
+ IF(DEBUG_PREFIX_MAP_RESULT MATCHES "foo=bar")
+ SET(DEBUG_PREFIX_FLAGS "${DEBUG_PREFIX_FLAGS} -gno-record-gcc-switches")
+ ENDIF()
+
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${DEBUG_PREFIX_FLAGS}")
+ SET(CMAKE_C_FLAGS_RELWITHDEBINFO
+ "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${DEBUG_PREFIX_FLAGS}")
+ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEBUG_PREFIX_FLAGS}")
+ SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO
+ "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${DEBUG_PREFIX_FLAGS}")
+
+ SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--build-id=none")
+ SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--build-id=none")
+
+ set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE
+ "${CMAKE_SOURCE_DIR}/scripts/invoke-with-relative-paths.pl")
+ENDIF()
+
OPTION(ENABLED_LOCAL_INFILE
"If we should should enable LOAD DATA LOCAL by default" ${IF_WIN})
MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE)
diff --git a/scripts/invoke-with-relative-paths.pl b/scripts/invoke-with-relative-paths.pl
new file mode 100755
index 00000000000..97480330b7f
--- /dev/null
+++ b/scripts/invoke-with-relative-paths.pl
@@ -0,0 +1,95 @@
+#! /usr/bin/perl
+#
+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
+#
+
+#
+# Take the given GCC command line and run it with all absolute paths
+# changed to relative paths. This makes sure that no part of the build
+# path leaks into the .o files, which it normally would through the
+# contents of __FILE__. (Debug information is also affected, but that
+# is already fixed through -fdebug-prefix-map=.)
+#
+# A more elegant solution would be -ffile-prefix-map=, but this is
+# not currently supported in GCC; see
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70268.
+#
+
+use strict;
+use warnings;
+use Cwd;
+
+my $cwd = getcwd();
+
+my @newarg = ();
+for my $i (0..$#ARGV) {
+ my $arg = $ARGV[$i];
+ if ($arg =~ /-I(.+)$/) {
+ $arg = '-I' . relativize($1, $cwd);
+ } elsif ($arg =~ /^\//) {
+ $arg = relativize($arg, $cwd);
+ }
+ push @newarg, $arg;
+}
+
+exec(@newarg);
+
+# /a/b/c/foo from /a/b/d = ../c/foo
+sub relativize {
+ my ($dir1, $dir2) = @_;
+
+ if ($dir1 !~ /^\//) {
+ # Not an absolute path.
+ return $dir1;
+ }
+
+ if (! -e $dir1) {
+# print STDERR "Unknown file/directory $dir1.\n";
+ return $dir1;
+ }
+ # Resolve symlinks and such, because getcwd() does.
+ $dir1 = Cwd::abs_path($dir1);
+
+ if ($dir1 =~ /^\/(lib|tmp|usr)/) {
+ # Not related to our source code.
+ return $dir1;
+ }
+
+ if ($dir1 eq $dir2) {
+ return ".";
+ }
+
+ my (@dir1_components) = split /\//, $dir1;
+ my (@dir2_components) = split /\//, $dir2;
+
+ # Remove common leading components.
+ while (scalar @dir1_components > 0 && scalar @dir2_components > 0 &&
+ $dir1_components[0] eq $dir2_components[0]) {
+ shift @dir1_components;
+ shift @dir2_components;
+ }
+
+ my $ret = "";
+ for my $i (0..$#dir2_components) {
+ $ret .= '../';
+ }
+ $ret .= join('/', @dir1_components);
+
+ # print STDERR "[$dir1] from [$dir2] => [$ret]\n";
+
+ return $ret;
+}
+
From 3b562dcf6e5423d41d41ef416c18187c3a946d9e Mon Sep 17 00:00:00 2001
From: Shishir Jaiswal
Date: Tue, 16 May 2017 13:48:52 +0530
Subject: [PATCH 026/101] Bug#16212207 - LOAD XML INFILE PERFORMANCE WITH
INDENTED XML
DESCRIPTION
===========
LOAD XML INFILE performance becomes painfully slow if the
tags' value has any space(s) in between them. They're
usually kept intentionally for indentation purpose.
ANALYSIS
========
The extra spaces are calling clear_level() many a times
which is having overhead of clearing taglist etc. This can
be avoided altogether by skipping all such spaces.
FIX
===
Trim all the starting whitespaces from the value before
passing it to read_value()
---
sql/sql_load.cc | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index c28c7cdb2db..a2c01c3b8a8 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1989,6 +1989,13 @@ int READ_INFO::read_xml()
case '>': /* end tag - read tag value */
in_tag= false;
+ /* Skip all whitespaces */
+ while (' ' == (chr= my_tospace(GET)));
+ /*
+ Push the first non-whitespace char back to Stack. This char would be
+ read in the upcoming call to read_value()
+ */
+ PUSH(chr);
chr= read_value('<', &value);
if(chr == my_b_EOF)
goto found_eof;
From 20addb05e58fdf822896f490fcaaf2ec5ed4bcb5 Mon Sep 17 00:00:00 2001
From: Ivo Roylev
Date: Mon, 22 May 2017 15:52:00 +0300
Subject: [PATCH 027/101] Bug# 25998635: Client does not escape the USE
statement
When there are quotes in the USE statement, the mysql client does
not correctly escape them.
The USE statement is processed line by line from the client's parser,
and cannot handle multi-line commands as the server.
The fix is to escape the USE parameters whenever quotes are used.
---
client/mysql.cc | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/client/mysql.cc b/client/mysql.cc
index 6e6dc4971ac..d09499c120a 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -3386,7 +3386,7 @@ print_table_data(MYSQL_RES *result)
length=4; // Room for "NULL"
if (opt_binhex && is_binary_field(field))
length= 2 + length * 2;
- field->max_length=length;
+ field->max_length=(ulong) length;
separator.fill(separator.length()+length+2,'-');
separator.append('+');
}
@@ -3453,7 +3453,7 @@ print_table_data(MYSQL_RES *result)
many extra padding-characters we should send with the printing function.
*/
visible_length= charset_info->cset->numcells(charset_info, buffer, buffer + data_length);
- extra_padding= data_length - visible_length;
+ extra_padding= (uint) (data_length - visible_length);
if (opt_binhex && is_binary_field(field))
print_as_hex(PAGER, cur[off], lengths[off], field_max_length);
@@ -4232,10 +4232,9 @@ com_use(String *buffer __attribute__((unused)), char *line)
bzero(buff, sizeof(buff));
/*
- In case number of quotes exceed 2, we try to get
- the normalized db name.
+ In case of quotes used, try to get the normalized db name.
*/
- if (get_quote_count(line) > 2)
+ if (get_quote_count(line) > 0)
{
if (normalize_dbname(line, buff, sizeof(buff)))
return put_error(&mysql);
@@ -4453,11 +4452,13 @@ char *get_arg(char *line, my_bool get_next_arg)
static int
get_quote_count(const char *line)
{
- int quote_count;
- const char *ptr= line;
+ int quote_count= 0;
+ const char *quote= line;
- for(quote_count= 0; ptr ++ && *ptr; ptr= strpbrk(ptr, "\"\'`"))
- quote_count ++;
+ while ((quote= strpbrk(quote, "'`\"")) != NULL) {
+ quote_count++;
+ quote++;
+ }
return quote_count;
}
From 8c7e9aab054360ec192ce3cffb2c25aa16e25f10 Mon Sep 17 00:00:00 2001
From: Shishir Jaiswal
Date: Tue, 23 May 2017 10:22:33 +0530
Subject: [PATCH 028/101] Bug#16212207 - LOAD XML INFILE PERFORMANCE WITH
INDENTED XML
Post-push fix for build failure on Linux machine
sles11-x86-64bit
---
sql/sql_load.cc | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index a2c01c3b8a8..6d6dc8b55e8 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -1990,7 +1990,9 @@ int READ_INFO::read_xml()
case '>': /* end tag - read tag value */
in_tag= false;
/* Skip all whitespaces */
- while (' ' == (chr= my_tospace(GET)));
+ while (' ' == (chr= my_tospace(GET)))
+ {
+ }
/*
Push the first non-whitespace char back to Stack. This char would be
read in the upcoming call to read_value()
From 3d8134d2c9b74bc8883ffe2ef59c168361223837 Mon Sep 17 00:00:00 2001
From: Harin Vadodaria
Date: Tue, 23 May 2017 07:14:33 +0200
Subject: [PATCH 029/101] Bug#25988681: USE-AFTER-FREE IN MYSQL_STMT_CLOSE()
Description: If mysql_stmt_close() encountered error,
it recorded error in prepared statement
but then frees memory assigned to prepared
statement. If mysql_stmt_error() is used
to get error information, it will result
into use after free.
In all cases where mysql_stmt_close() can
fail, error would have been set by
cli_advanced_command in MYSQL structure.
Solution: Don't copy error from MYSQL using set_stmt_errmsg.
There is no automated way to test the fix since
it is in mysql_stmt_close() which does not expect
any reply from server.
Reviewed-By: Georgi Kodinov
Reviewed-By: Ramil Kalimullin
---
libmysql/libmysql.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 6e7134ff97c..d5ab85efa32 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -4678,10 +4678,14 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
mysql->status= MYSQL_STATUS_READY;
}
int4store(buff, stmt->stmt_id);
- if ((rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt)))
- {
- set_stmt_errmsg(stmt, &mysql->net);
- }
+ /*
+ If stmt_command failed, it would have already raised
+ error using set_mysql_error. Caller should use
+ mysql_error() or mysql_errno() to find out details.
+ Memory allocated for stmt will be released regardless
+ of the error.
+ */
+ rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt);
}
}
From ba15ff2aaaa208c90fdb996c880af28d2b5a0353 Mon Sep 17 00:00:00 2001
From: "mysql-builder@oracle.com" <>
Date: Tue, 23 May 2017 11:24:23 +0300
Subject: [PATCH 030/101]
From c34f2e518a141ac117eaa4d08ca283d4440752b6 Mon Sep 17 00:00:00 2001
From: Sreeharsha Ramanavarapu
Date: Wed, 24 May 2017 08:50:05 +0530
Subject: [PATCH 031/101] Bug #24595639: INCORRECT BEHAVIOR IN QUERY WITH UNION
AND GROUP BY
Issue 1:
--------
This problem occurs in the following conditions:
1) A UNION is present in the subquery of select list and
handles multiple columns.
2) Query has a GROUP BY.
A temporary table is created to handle the UNION.
Item_field objects are based on the expressions of the
result of the UNION (ie. the fake_select_lex). While
checking validity of the columns in the GROUP BY list, the
columns of the temporary table are checked in
Item_ident::local_column. But the Item_field objects
created for the temporary table don't have information like
the Name_resolution_context that they belong to or whether
they are dependent on an outer query. Since these members
are null, incorrect behavior is caused.
This can happen when such Item objects are cached to apply
the IN-to-EXISTS transform for Item_row.
Solution to Issue 1:
--------------------
Context information of the first select in the UNION will
be assigned to the new Item_field objects.
Issue 2:
--------
This problem occurs in the following conditions:
1) A UNION is present in the subquery of select list.
2) A column in the UNION's first SELECT refers to a table
in the outer-query making it a dependent union.
3) GROUP BY column refers to the outer-referencing column.
While resolving the select list with an outer-reference, an
Item_outer_ref object is created to handle the
outer-query's GROUP BY list. The Item_outer_ref object
replaces the Item_field object in the item tree.
Item_outer_ref::fix_fields will be called only while fixing
the inner references of the outer query.
Before resolving the outer-query, an Item_type_holder
object needs to be created to handle the UNION. But as
explained above, the Item_outer_ref object has not been
fixed yet. Having a fixed Item object is a pre-condition
for creating an Item_type_holder.
Solution to Issue 2:
--------------------
Use the reference (real_item()) of an Item_outer_ref object
instead of the object itself while creating an
Item_type_holder.
---
sql/item.cc | 5 ++++-
sql/sql_union.cc | 15 ++++++++++++++-
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/sql/item.cc b/sql/item.cc
index 34157c33cf4..6f1fdaae398 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1949,6 +1949,9 @@ Item_field::Item_field(Field *f)
item_equal(0), no_const_subst(0),
have_privileges(0), any_privileges(0)
{
+ if (f->table->pos_in_table_list != NULL)
+ context= &(f->table->pos_in_table_list->select_lex->context);
+
set_field(f);
/*
field_name and table_name should not point to garbage
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index d230b903d2c..ca6870dab9c 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -282,6 +282,19 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
Item *item_tmp;
while ((item_tmp= it++))
{
+ /*
+ If the outer query has a GROUP BY clause, an outer reference to this
+ query block may have been wrapped in a Item_outer_ref, which has not
+ been fixed yet. An Item_type_holder must be created based on a fixed
+ Item, so use the inner Item instead.
+ */
+ DBUG_ASSERT(item_tmp->fixed ||
+ (item_tmp->type() == Item::REF_ITEM &&
+ ((Item_ref *)(item_tmp))->ref_type() ==
+ Item_ref::OUTER_REF));
+ if (!item_tmp->fixed)
+ item_tmp= item_tmp->real_item();
+
/* Error's in 'new' will be detected after loop */
types.push_back(new Item_type_holder(thd_arg, item_tmp));
}
From fedfba217165f78745001a6f1043d847df3a9510 Mon Sep 17 00:00:00 2001
From: Piotr Obrzut
Date: Wed, 24 May 2017 18:09:17 +0200
Subject: [PATCH 032/101] Bug #25658832 VALIDATION CHECK FOR MSVC REDIST NEEDED
IN SERVER COMMUNITY MSI
Added matching redist prerequisite check to the server msi installer.
---
packaging/WiX/create_msi.cmake.in | 3 ++-
packaging/WiX/mysql_server.wxs.in | 28 +++++++++++++++++++++++++++-
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/packaging/WiX/create_msi.cmake.in b/packaging/WiX/create_msi.cmake.in
index 8de271fc1cf..95cbbb3d437 100644
--- a/packaging/WiX/create_msi.cmake.in
+++ b/packaging/WiX/create_msi.cmake.in
@@ -1,4 +1,4 @@
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -13,6 +13,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+SET(LINK_STATIC_RUNTIME_LIBRARIES "@LINK_STATIC_RUNTIME_LIBRARIES@")
SET(CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@")
SET(CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@")
SET(CANDLE_EXECUTABLE "@CANDLE_EXECUTABLE@")
diff --git a/packaging/WiX/mysql_server.wxs.in b/packaging/WiX/mysql_server.wxs.in
index 10b6f892a2e..2092d0ebe3d 100644
--- a/packaging/WiX/mysql_server.wxs.in
+++ b/packaging/WiX/mysql_server.wxs.in
@@ -2,7 +2,7 @@
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
From bb9e547a860432972739e6661d15c52d8c008748 Mon Sep 17 00:00:00 2001
From: Venkatesh Duggirala
Date: Wed, 24 May 2017 16:12:57 +0530
Subject: [PATCH 033/101] Bug#18950197 RPL_SEMI_SYNC_UNINSTALL_PLUGIN FAILS
BECAUSE RPL_SEMI_SYNC_MASTER_CLIENTS=1
Analysis: Uninstalling rpl_semi_sync_slave on slave
will trigger removing the slave logic on Master which
will reduce Rpl_semi_sync_master_clients by one number.
But it happens asynchronously on Master. Having assert
to check this value with zero will have problems on
slow pb2 machines.
Fix: Change assert into wait_for_status_var condition.
---
.../suite/rpl/r/rpl_semi_sync_uninstall_plugin.result | 1 -
.../suite/rpl/t/rpl_semi_sync_uninstall_plugin.test | 9 ++++-----
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result b/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result
index bd659e71600..347e6de4dd7 100644
--- a/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result
+++ b/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result
@@ -28,7 +28,6 @@ include/stop_slave.inc
SET GLOBAL rpl_semi_sync_slave_enabled = OFF;
include/start_slave.inc
UNINSTALL PLUGIN rpl_semi_sync_slave;
-include/assert.inc [semi sync master clients should be 0.]
UNINSTALL PLUGIN rpl_semi_sync_master;
CREATE TABLE t1(i int);
INSERT INTO t1 values (3);
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test b/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test
index 2badd4203cf..a3a3da8b18a 100644
--- a/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test
@@ -125,12 +125,11 @@ SET GLOBAL rpl_semi_sync_slave_enabled = OFF;
# Step 4.4: Uninstall semi sync plugin, it should be successful now.
UNINSTALL PLUGIN rpl_semi_sync_slave;
-# Step 4.5: On Master, check that semi sync slaves are now '0'.
+# Step 4.5: On Master, wait until semi sync slaves is '0'.
--connection master
---let $master_clients=[show status like "Rpl_semi_sync_master_clients", Value, 1]
---let assert_cond= $master_clients = 0
---let assert_text= semi sync master clients should be 0.
---source include/assert.inc
+--let $status_var= Rpl_semi_sync_master_clients
+--let $status_var_value= 0
+--source include/wait_for_status_var.inc
# Step 4.6: So uninstalling semi sync plugin should be allowed
UNINSTALL PLUGIN rpl_semi_sync_master;
From 88915a3090d34a02d71b79001addc2fea00016c6 Mon Sep 17 00:00:00 2001
From: Piotr Obrzut
Date: Thu, 1 Jun 2017 15:25:04 +0200
Subject: [PATCH 034/101] Bug#26181622 MSI BUILD FAIL DUE TO DUPLICATED FILE ID
Fixed generated mysql_server.wxs not to contain duplicates, or too long ids
(cherry picked from commit bf47fb74dcc3e84057314817c56e6f8e05af094c)
---
packaging/WiX/create_msi.cmake.in | 29 ++++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/packaging/WiX/create_msi.cmake.in b/packaging/WiX/create_msi.cmake.in
index 95cbbb3d437..b306c0c70d3 100644
--- a/packaging/WiX/create_msi.cmake.in
+++ b/packaging/WiX/create_msi.cmake.in
@@ -218,22 +218,37 @@ MACRO(GENERATE_GUID VarName)
OUTPUT_STRIP_TRAILING_WHITESPACE)
ENDMACRO()
-SET(INC_VAR 0)
+# Make sure that WIX identifier created from a path matches all the rules:
+# - it is shorter than 72 characters
+# - doesn't contain reserver characters ('+', '-' and '/')
+# ID_SET contains a global list of all identifiers which are too long.
+# Every time we use an identifier which is too long we use its index in
+# ID_SET to shorten the name.
+SET_PROPERTY(GLOBAL PROPERTY ID_SET)
MACRO(MAKE_WIX_IDENTIFIER str varname)
STRING(REPLACE "/" "." ${varname} "${str}")
+ STRING(REPLACE "+" "p" ${varname} "${str}")
+ STRING(REPLACE "-" "m" ${varname} "${str}")
STRING(REGEX REPLACE "[^a-zA-Z_0-9.]" "_" ${varname} "${${varname}}")
STRING(LENGTH "${${varname}}" len)
+ # FIXME: the prefix length has to be controlled better
# Identifier should be smaller than 72 character
- # We have to cut down the length to 70 chars, since we add 2 char prefix
+ # We have to cut down the length to 40 chars, since we add prefixes
# pretty often
- IF(len GREATER 70)
- STRING(SUBSTRING "${${varname}}" 0 67 shortstr)
- MATH(EXPR INC_VAR ${INC_VAR}+1)
- SET(${varname} "${shortstr}${INC_VAR}")
+ IF(len GREATER 40)
+ STRING(SUBSTRING "${${varname}}" 0 37 shortstr)
+ GET_PROPERTY(LOCAL_LIST GLOBAL PROPERTY ID_SET)
+ LIST(FIND LOCAL_LIST "${${varname}}" STRING_ID)
+ IF(${STRING_ID} EQUAL -1)
+ LIST(APPEND LOCAL_LIST "${${varname}}")
+ SET_PROPERTY(GLOBAL PROPERTY ID_SET "${LOCAL_LIST}")
+ LIST(LENGTH LOCAL_LIST STRING_ID)
+ MATH(EXPR STRING_ID "${STRING_ID}-1" )
+ ENDIF()
+ SET(${varname} "${shortstr}${STRING_ID}")
ENDIF()
ENDMACRO()
-
FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root)
FILE(RELATIVE_PATH dir_rel ${topdir} ${dir})
IF(dir_rel)
From c3e6a032c3acbfc56fb3cc7b38710a24c416ffd0 Mon Sep 17 00:00:00 2001
From: Piotr Obrzut
Date: Fri, 2 Jun 2017 19:17:30 +0200
Subject: [PATCH 035/101] Bug#26171638 MYSQL 5.5.57 - MSI COMMUNITY PACKAGES
NOT GETTING INSTALLED
Temporary revert of the VS2008 redist check.
(cherry picked from commit 36ec550fe5fa6b2a997cb39d3b9e33988f525c96)
---
packaging/WiX/create_msi.cmake.in | 31 -------------------------------
1 file changed, 31 deletions(-)
diff --git a/packaging/WiX/create_msi.cmake.in b/packaging/WiX/create_msi.cmake.in
index b306c0c70d3..ae6a5773dce 100644
--- a/packaging/WiX/create_msi.cmake.in
+++ b/packaging/WiX/create_msi.cmake.in
@@ -218,37 +218,6 @@ MACRO(GENERATE_GUID VarName)
OUTPUT_STRIP_TRAILING_WHITESPACE)
ENDMACRO()
-# Make sure that WIX identifier created from a path matches all the rules:
-# - it is shorter than 72 characters
-# - doesn't contain reserver characters ('+', '-' and '/')
-# ID_SET contains a global list of all identifiers which are too long.
-# Every time we use an identifier which is too long we use its index in
-# ID_SET to shorten the name.
-SET_PROPERTY(GLOBAL PROPERTY ID_SET)
-MACRO(MAKE_WIX_IDENTIFIER str varname)
- STRING(REPLACE "/" "." ${varname} "${str}")
- STRING(REPLACE "+" "p" ${varname} "${str}")
- STRING(REPLACE "-" "m" ${varname} "${str}")
- STRING(REGEX REPLACE "[^a-zA-Z_0-9.]" "_" ${varname} "${${varname}}")
- STRING(LENGTH "${${varname}}" len)
- # FIXME: the prefix length has to be controlled better
- # Identifier should be smaller than 72 character
- # We have to cut down the length to 40 chars, since we add prefixes
- # pretty often
- IF(len GREATER 40)
- STRING(SUBSTRING "${${varname}}" 0 37 shortstr)
- GET_PROPERTY(LOCAL_LIST GLOBAL PROPERTY ID_SET)
- LIST(FIND LOCAL_LIST "${${varname}}" STRING_ID)
- IF(${STRING_ID} EQUAL -1)
- LIST(APPEND LOCAL_LIST "${${varname}}")
- SET_PROPERTY(GLOBAL PROPERTY ID_SET "${LOCAL_LIST}")
- LIST(LENGTH LOCAL_LIST STRING_ID)
- MATH(EXPR STRING_ID "${STRING_ID}-1" )
- ENDIF()
- SET(${varname} "${shortstr}${STRING_ID}")
- ENDIF()
-ENDMACRO()
-
FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root)
FILE(RELATIVE_PATH dir_rel ${topdir} ${dir})
IF(dir_rel)
From 34cd74e52185de2ea3156e8295de3c638cde8c88 Mon Sep 17 00:00:00 2001
From: Piotr Obrzut
Date: Mon, 5 Jun 2017 08:09:07 +0200
Subject: [PATCH 036/101] Bug#26171638 MYSQL 5.5.57 - MSI COMMUNITY PACKAGES
NOT GETTING INSTALLED
Corrected the revert.
(cherry picked from commit f637e524bf9b692c3ed46d856e2beac193b42a3e)
---
packaging/WiX/create_msi.cmake.in | 31 +++++++++++++++++++++++++++++++
packaging/WiX/mysql_server.wxs.in | 26 --------------------------
2 files changed, 31 insertions(+), 26 deletions(-)
diff --git a/packaging/WiX/create_msi.cmake.in b/packaging/WiX/create_msi.cmake.in
index ae6a5773dce..b306c0c70d3 100644
--- a/packaging/WiX/create_msi.cmake.in
+++ b/packaging/WiX/create_msi.cmake.in
@@ -218,6 +218,37 @@ MACRO(GENERATE_GUID VarName)
OUTPUT_STRIP_TRAILING_WHITESPACE)
ENDMACRO()
+# Make sure that WIX identifier created from a path matches all the rules:
+# - it is shorter than 72 characters
+# - doesn't contain reserver characters ('+', '-' and '/')
+# ID_SET contains a global list of all identifiers which are too long.
+# Every time we use an identifier which is too long we use its index in
+# ID_SET to shorten the name.
+SET_PROPERTY(GLOBAL PROPERTY ID_SET)
+MACRO(MAKE_WIX_IDENTIFIER str varname)
+ STRING(REPLACE "/" "." ${varname} "${str}")
+ STRING(REPLACE "+" "p" ${varname} "${str}")
+ STRING(REPLACE "-" "m" ${varname} "${str}")
+ STRING(REGEX REPLACE "[^a-zA-Z_0-9.]" "_" ${varname} "${${varname}}")
+ STRING(LENGTH "${${varname}}" len)
+ # FIXME: the prefix length has to be controlled better
+ # Identifier should be smaller than 72 character
+ # We have to cut down the length to 40 chars, since we add prefixes
+ # pretty often
+ IF(len GREATER 40)
+ STRING(SUBSTRING "${${varname}}" 0 37 shortstr)
+ GET_PROPERTY(LOCAL_LIST GLOBAL PROPERTY ID_SET)
+ LIST(FIND LOCAL_LIST "${${varname}}" STRING_ID)
+ IF(${STRING_ID} EQUAL -1)
+ LIST(APPEND LOCAL_LIST "${${varname}}")
+ SET_PROPERTY(GLOBAL PROPERTY ID_SET "${LOCAL_LIST}")
+ LIST(LENGTH LOCAL_LIST STRING_ID)
+ MATH(EXPR STRING_ID "${STRING_ID}-1" )
+ ENDIF()
+ SET(${varname} "${shortstr}${STRING_ID}")
+ ENDIF()
+ENDMACRO()
+
FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root)
FILE(RELATIVE_PATH dir_rel ${topdir} ${dir})
IF(dir_rel)
diff --git a/packaging/WiX/mysql_server.wxs.in b/packaging/WiX/mysql_server.wxs.in
index 2092d0ebe3d..3eb81ec532c 100644
--- a/packaging/WiX/mysql_server.wxs.in
+++ b/packaging/WiX/mysql_server.wxs.in
@@ -61,32 +61,6 @@
-
-
-
-
-
-
-
- Installed OR VS08REDISTX64
-
-
-
-
-
-
- Installed OR VS08REDISTX86
-
-
-
From a06f2f430f6cfd55929c3734b24e04fa70803156 Mon Sep 17 00:00:00 2001
From: Alexey Botchkov
Date: Tue, 14 Mar 2017 16:35:39 +0400
Subject: [PATCH 037/101] MDEV-12078 Using spatial index changes type from
point to geometry
In get_mm_tree we have to change Field_geom::geom_type to
GEOMETRY as we have to let storing all types of the spatial features
in the field. So now we restore the original geom_type as it's
done.
---
mysql-test/r/gis-rt-precise.result | 22 ++++++++++++++++++++++
mysql-test/t/gis-rt-precise.test | 22 ++++++++++++++++++++++
sql/opt_range.cc | 9 +++++++++
3 files changed, 53 insertions(+)
diff --git a/mysql-test/r/gis-rt-precise.result b/mysql-test/r/gis-rt-precise.result
index 3f4f014fb78..65583a0ce0d 100644
--- a/mysql-test/r/gis-rt-precise.result
+++ b/mysql-test/r/gis-rt-precise.result
@@ -60,3 +60,25 @@ fid AsText(g)
45 LINESTRING(51 51,60 60)
DROP TABLE t1;
End of 5.5 tests.
+CREATE TABLE t1 (
+coordinate point NOT NULL,
+SPATIAL KEY coordinate (coordinate)
+) ENGINE=Aria DEFAULT CHARSET=ascii PAGE_CHECKSUM=1;
+SHOW COLUMNS FROM t1;
+Field Type Null Key Default Extra
+coordinate point NO MUL NULL
+INSERT INTO t1 (coordinate) VALUES(ST_PointFromText("POINT(0 0)"));
+INSERT INTO t1 (coordinate) VALUES(ST_PointFromText("POINT(10 0)"));
+INSERT INTO t1 (coordinate) VALUES(ST_PointFromText("POINT(10 10)"));
+INSERT INTO t1 (coordinate) VALUES(ST_PointFromText("POINT(0 10)"));
+INSERT INTO t1 (coordinate) VALUES(ST_PointFromText("POINT(5 5)"));
+SELECT astext(coordinate) FROM t1 WHERE ST_Intersects(ST_LineFromText("LINESTRING(0 0, 10 0, 10 10, 0 10)"), coordinate);
+astext(coordinate)
+POINT(0 0)
+POINT(10 0)
+POINT(10 10)
+POINT(0 10)
+SHOW COLUMNS FROM t1;
+Field Type Null Key Default Extra
+coordinate point NO MUL NULL
+DROP TABLE t1;
diff --git a/mysql-test/t/gis-rt-precise.test b/mysql-test/t/gis-rt-precise.test
index 4cae10a9076..9c26aa05598 100644
--- a/mysql-test/t/gis-rt-precise.test
+++ b/mysql-test/t/gis-rt-precise.test
@@ -62,3 +62,25 @@ SELECT fid, AsText(g) FROM t1 WHERE ST_Within(g,
DROP TABLE t1;
--echo End of 5.5 tests.
+
+#
+# MDEV-12078 Using spatial index changes type from point to geometry.
+#
+CREATE TABLE t1 (
+ coordinate point NOT NULL,
+ SPATIAL KEY coordinate (coordinate)
+) ENGINE=Aria DEFAULT CHARSET=ascii PAGE_CHECKSUM=1;
+
+SHOW COLUMNS FROM t1;
+
+INSERT INTO t1 (coordinate) VALUES(ST_PointFromText("POINT(0 0)"));
+INSERT INTO t1 (coordinate) VALUES(ST_PointFromText("POINT(10 0)"));
+INSERT INTO t1 (coordinate) VALUES(ST_PointFromText("POINT(10 10)"));
+INSERT INTO t1 (coordinate) VALUES(ST_PointFromText("POINT(0 10)"));
+INSERT INTO t1 (coordinate) VALUES(ST_PointFromText("POINT(5 5)"));
+
+SELECT astext(coordinate) FROM t1 WHERE ST_Intersects(ST_LineFromText("LINESTRING(0 0, 10 0, 10 10, 0 10)"), coordinate);
+
+SHOW COLUMNS FROM t1;
+
+DROP TABLE t1;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 481d8445fa8..3563058282b 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -7949,8 +7949,10 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param,
DBUG_ENTER("get_full_func_mm_tree");
#ifdef HAVE_SPATIAL
+ Field::geometry_type sav_geom_type;
if (field_item->field->type() == MYSQL_TYPE_GEOMETRY)
{
+ sav_geom_type= ((Field_geom*) field_item->field)->geom_type;
/* We have to be able to store all sorts of spatial features here */
((Field_geom*) field_item->field)->geom_type= Field::GEOM_GEOMETRY;
}
@@ -7982,6 +7984,13 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param,
}
}
}
+
+#ifdef HAVE_SPATIAL
+ if (field_item->field->type() == MYSQL_TYPE_GEOMETRY)
+ {
+ ((Field_geom*) field_item->field)->geom_type= sav_geom_type;
+ }
+#endif /*HAVE_SPATIAL*/
DBUG_RETURN(ftree);
}
From c5975eaea174460e774e77717e972a8d32e6c8de Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Wed, 12 Jul 2017 08:05:42 +0200
Subject: [PATCH 038/101] MDEV-7339 Server crashes in
Item_func_trig_cond::val_int
Item_in_subselect::pushed_cond_guards[] array is allocated only when
left_expr->maybe_null. And it is used (for row expressions) when
left_expr->element_index(i)->maybe_null.
For left_expr being a multi-column subquery, its maybe_null is
always false when the subquery doesn't use tables (see
Item_singlerow_subselect::fix_length_and_dec()
and subselect_single_select_engine::fix_length_and_dec()),
otherwise it's always true.
But row elements can be NULL regardless, so let's always allocate
pushed_cond_guards for multi-column subqueries, no matter whether
its maybe_null was forced to true or false.
---
mysql-test/r/subselect_nulls.result | 6 ++++++
mysql-test/t/subselect_nulls.test | 6 ++++++
sql/item_subselect.cc | 3 ++-
3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/mysql-test/r/subselect_nulls.result b/mysql-test/r/subselect_nulls.result
index 584c184870d..08982371269 100644
--- a/mysql-test/r/subselect_nulls.result
+++ b/mysql-test/r/subselect_nulls.result
@@ -115,3 +115,9 @@ k d1 d2
set optimizer_switch= @tmp_subselect_nulls;
drop table x1;
drop table x2;
+select (select 1, 2) in (select 3, 4);
+(select 1, 2) in (select 3, 4)
+0
+select (select NULL, NULL) in (select 3, 4);
+(select NULL, NULL) in (select 3, 4)
+NULL
diff --git a/mysql-test/t/subselect_nulls.test b/mysql-test/t/subselect_nulls.test
index 4b08e773b17..3e7b2189ed5 100644
--- a/mysql-test/t/subselect_nulls.test
+++ b/mysql-test/t/subselect_nulls.test
@@ -97,3 +97,9 @@ set optimizer_switch= @tmp_subselect_nulls;
drop table x1;
drop table x2;
+
+#
+# MDEV-7339 Server crashes in Item_func_trig_cond::val_int
+#
+select (select 1, 2) in (select 3, 4);
+select (select NULL, NULL) in (select 3, 4);
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index e0da946d190..068f32c99b9 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -2871,7 +2871,8 @@ bool Item_in_subselect::init_cond_guards()
{
DBUG_ASSERT(thd);
uint cols_num= left_expr->cols();
- if (!abort_on_null && left_expr->maybe_null && !pushed_cond_guards)
+ if (!abort_on_null && !pushed_cond_guards &&
+ (left_expr->maybe_null || cols_num > 1))
{
if (!(pushed_cond_guards= (bool*)thd->alloc(sizeof(bool) * cols_num)))
return TRUE;
From be55bbc2b206f2fe295ad4179b23791c3119fe02 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Wed, 12 Jul 2017 12:49:29 +0200
Subject: [PATCH 039/101] MDEV-7826 Server crashes in
Item_subselect::enumerate_field_refs_processor
upper->item can be NULL if we're referring to an aggregate function
---
mysql-test/r/group_by.result | 14 ++++++++++++++
mysql-test/t/group_by.test | 19 +++++++++++++++++++
sql/item_subselect.cc | 3 ++-
3 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 262bb2ebd84..2bd3c5c5c3d 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -2531,3 +2531,17 @@ select a from t1 group by a having a > 1;
a
drop table t1;
set sql_mode= @save_sql_mode;
+create table t1 (f1 int);
+insert into t1 values (5),(9);
+create table t2 (f2 int);
+insert into t2 values (0),(6);
+create table t3 (f3 int);
+insert into t3 values (6),(3);
+create table t4 (f4 int);
+insert into t4 values (1),(0);
+select
+(select min(f1) from t1 where f1 in (select min(f4) from t2)) as field7,
+(select count(*) from t3 where f3 in (select max(f4) from t2 group by field7))
+from t4;
+ERROR 42S22: Reference 'field7' not supported (reference to group function)
+drop table t1, t2, t3, t4;
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 4162e9c67a1..9117262d9b0 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -1703,6 +1703,25 @@ select a as x from t1 group by x having x > 1;
select a from t1 group by a having a > 1;
drop table t1;
set sql_mode= @save_sql_mode;
+
+#
+# MDEV-7826 Server crashes in Item_subselect::enumerate_field_refs_processor
+#
+create table t1 (f1 int);
+insert into t1 values (5),(9);
+create table t2 (f2 int);
+insert into t2 values (0),(6);
+create table t3 (f3 int);
+insert into t3 values (6),(3);
+create table t4 (f4 int);
+insert into t4 values (1),(0);
+--error ER_ILLEGAL_REFERENCE
+select
+(select min(f1) from t1 where f1 in (select min(f4) from t2)) as field7,
+(select count(*) from t3 where f3 in (select max(f4) from t2 group by field7))
+from t4;
+drop table t1, t2, t3, t4;
+
#
# End of MariaDB 5.5 tests
#
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 068f32c99b9..ef90dd59be3 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -316,7 +316,8 @@ bool Item_subselect::enumerate_field_refs_processor(uchar *arg)
while ((upper= it++))
{
- if (upper->item->walk(&Item::enumerate_field_refs_processor, FALSE, arg))
+ if (upper->item &&
+ upper->item->walk(&Item::enumerate_field_refs_processor, FALSE, arg))
return TRUE;
}
return FALSE;
From d2e66a6f199bd3c9e3fe82aabe617b8bf337aa01 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Wed, 12 Jul 2017 13:46:15 +0200
Subject: [PATCH 040/101] MDEV-7828 Assertion `key_read == 0' failed in
TABLE::enable_keyread with SELECT SQ and WHERE SQ
already fixed by a7ed4644a6f.
just add a test case,
---
mysql-test/r/subselect.result | 8 ++++++++
mysql-test/r/subselect_no_mat.result | 8 ++++++++
mysql-test/r/subselect_no_opts.result | 8 ++++++++
mysql-test/r/subselect_no_scache.result | 8 ++++++++
mysql-test/r/subselect_no_semijoin.result | 8 ++++++++
mysql-test/t/subselect.test | 10 ++++++++++
6 files changed, 50 insertions(+)
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 000d8927542..8fc9cd38728 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -7138,3 +7138,11 @@ SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1;
ERROR 21000: Subquery returns more than 1 row
drop view v1;
drop table t1,t2;
+CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
+INSERT t1 VALUES (4),(8);
+CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
+INSERT t2 VALUES (6),(9);
+SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+(SELECT MAX(sq.f2) FROM t1)
+NULL
+drop table t1, t2;
diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
index 914f20d502a..a71df97e6bc 100644
--- a/mysql-test/r/subselect_no_mat.result
+++ b/mysql-test/r/subselect_no_mat.result
@@ -7135,6 +7135,14 @@ SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1;
ERROR 21000: Subquery returns more than 1 row
drop view v1;
drop table t1,t2;
+CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
+INSERT t1 VALUES (4),(8);
+CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
+INSERT t2 VALUES (6),(9);
+SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+(SELECT MAX(sq.f2) FROM t1)
+NULL
+drop table t1, t2;
set optimizer_switch=default;
select @@optimizer_switch like '%materialization=on%';
@@optimizer_switch like '%materialization=on%'
diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result
index 1b25e16ba7c..2f8c67fa167 100644
--- a/mysql-test/r/subselect_no_opts.result
+++ b/mysql-test/r/subselect_no_opts.result
@@ -7133,4 +7133,12 @@ SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1;
ERROR 21000: Subquery returns more than 1 row
drop view v1;
drop table t1,t2;
+CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
+INSERT t1 VALUES (4),(8);
+CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
+INSERT t2 VALUES (6),(9);
+SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+(SELECT MAX(sq.f2) FROM t1)
+NULL
+drop table t1, t2;
set @optimizer_switch_for_subselect_test=null;
diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result
index 90a11fbce7d..8dda0a4fd36 100644
--- a/mysql-test/r/subselect_no_scache.result
+++ b/mysql-test/r/subselect_no_scache.result
@@ -7144,6 +7144,14 @@ SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1;
ERROR 21000: Subquery returns more than 1 row
drop view v1;
drop table t1,t2;
+CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
+INSERT t1 VALUES (4),(8);
+CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
+INSERT t2 VALUES (6),(9);
+SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+(SELECT MAX(sq.f2) FROM t1)
+NULL
+drop table t1, t2;
set optimizer_switch=default;
select @@optimizer_switch like '%subquery_cache=on%';
@@optimizer_switch like '%subquery_cache=on%'
diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result
index 936aae07227..339e2b89786 100644
--- a/mysql-test/r/subselect_no_semijoin.result
+++ b/mysql-test/r/subselect_no_semijoin.result
@@ -7133,5 +7133,13 @@ SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1;
ERROR 21000: Subquery returns more than 1 row
drop view v1;
drop table t1,t2;
+CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
+INSERT t1 VALUES (4),(8);
+CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
+INSERT t2 VALUES (6),(9);
+SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+(SELECT MAX(sq.f2) FROM t1)
+NULL
+drop table t1, t2;
set @optimizer_switch_for_subselect_test=null;
set @join_cache_level_for_subselect_test=NULL;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index c5f5b229656..50d9517043a 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -6023,3 +6023,13 @@ SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1;
drop view v1;
drop table t1,t2;
+
+#
+# MDEV-7828 Assertion `key_read == 0' failed in TABLE::enable_keyread with SELECT SQ and WHERE SQ
+#
+CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
+INSERT t1 VALUES (4),(8);
+CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
+INSERT t2 VALUES (6),(9);
+SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+drop table t1, t2;
From c83d6ff881dcfd1cc68124a9663c2a31ca7e2dce Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Wed, 12 Jul 2017 13:55:04 +0200
Subject: [PATCH 041/101] compiler warning
remove unused variable
---
sql/item.cc | 1 -
1 file changed, 1 deletion(-)
diff --git a/sql/item.cc b/sql/item.cc
index 68411860274..61ad4bdb853 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -5048,7 +5048,6 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
if (thd->lex->in_sum_func &&
thd->lex->in_sum_func->nest_level >= select->nest_level)
{
- Item::Type ref_type= (*reference)->type();
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
select->nest_level);
}
From 05b678bc8c166c9015ca3dc3ccd9e9c89094f3ca Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Wed, 12 Jul 2017 14:21:41 +0200
Subject: [PATCH 042/101] MDEV-12489 The select stmt may fail due to "having
clause is ambiguous" unexpected
only compare field references with an alias (from the SELECT clause)
when this reference doesn't specify an explicit table name part.
---
mysql-test/r/group_by.result | 5 +++++
mysql-test/t/group_by.test | 8 ++++++++
sql/item.cc | 2 +-
3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 2bd3c5c5c3d..7744d98bc11 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -2545,3 +2545,8 @@ select
from t4;
ERROR 42S22: Reference 'field7' not supported (reference to group function)
drop table t1, t2, t3, t4;
+create table t1 (c1 int, c2 int);
+create table t2 (c1 int, c2 int);
+select t1.c1 as c1, t2.c2 as c1 from t1, t2 where t1.c1 < 20 and t2.c2 > 5 group by t1.c1, t2.c2 having t1.c1 < 3;
+c1 c1
+drop table t1, t2;
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 9117262d9b0..c137edeeba5 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -1722,6 +1722,14 @@ select
from t4;
drop table t1, t2, t3, t4;
+#
+# MDEV-12489 The select stmt may fail due to "having clause is ambiguous" unexpected
+#
+create table t1 (c1 int, c2 int);
+create table t2 (c1 int, c2 int);
+select t1.c1 as c1, t2.c2 as c1 from t1, t2 where t1.c1 < 20 and t2.c2 > 5 group by t1.c1, t2.c2 having t1.c1 < 3;
+drop table t1, t2;
+
#
# End of MariaDB 5.5 tests
#
diff --git a/sql/item.cc b/sql/item.cc
index 61ad4bdb853..b7dac96d418 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -4622,7 +4622,7 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
int cur_match_degree= 0;
/* SELECT list element with explicit alias */
- if ((*(cur_group->item))->name &&
+ if ((*(cur_group->item))->name && !table_name &&
!(*(cur_group->item))->is_autogenerated_name &&
!my_strcasecmp(system_charset_info,
(*(cur_group->item))->name, field_name))
From 181d9d2892739629382727cf956364106c947ea2 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Wed, 12 Jul 2017 15:54:04 +0200
Subject: [PATCH 043/101] MDEV-13180 Unused left join causes server crash
already fixed by be55bbc2b20
just add a test case
---
mysql-test/r/group_by.result | 8 ++++++++
mysql-test/t/group_by.test | 11 +++++++++++
2 files changed, 19 insertions(+)
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 7744d98bc11..b948c9a6f88 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -2545,6 +2545,14 @@ select
from t4;
ERROR 42S22: Reference 'field7' not supported (reference to group function)
drop table t1, t2, t3, t4;
+create table t1 (i1 int);
+insert into t1 values (1);
+create table t2 (i int);
+insert into t2 values (2);
+select 1 from t1 left join t2 b on b.i = (select max(b.i) from t2);
+1
+1
+drop table t1, t2;
create table t1 (c1 int, c2 int);
create table t2 (c1 int, c2 int);
select t1.c1 as c1, t2.c2 as c1 from t1, t2 where t1.c1 < 20 and t2.c2 > 5 group by t1.c1, t2.c2 having t1.c1 < 3;
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index c137edeeba5..80ecfea539b 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -1722,6 +1722,17 @@ select
from t4;
drop table t1, t2, t3, t4;
+#
+# MDEV-13180 Unused left join causes server crash
+#
+create table t1 (i1 int);
+insert into t1 values (1);
+create table t2 (i int);
+insert into t2 values (2);
+select 1 from t1 left join t2 b on b.i = (select max(b.i) from t2);
+drop table t1, t2;
+
+
#
# MDEV-12489 The select stmt may fail due to "having clause is ambiguous" unexpected
#
From e7f51e5d269ba8adb917226724564274a57d07b3 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Wed, 12 Jul 2017 19:20:52 +0200
Subject: [PATCH 044/101] MDEV-12136 SELECT COUNT(DISTINCT) returns the wrong
value when tmp_table_size is limited
use the correct value for the merge_buffer size, max_in_memory_size
is too small and merge_walk() fails.
also: remove a cast.
---
mysql-test/r/count_distinct.result | 8 ++++++++
mysql-test/t/count_distinct.test | 14 ++++++++++++++
sql/uniques.cc | 6 +++---
3 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/mysql-test/r/count_distinct.result b/mysql-test/r/count_distinct.result
index 3b65dd0e608..3decd5f60bc 100644
--- a/mysql-test/r/count_distinct.result
+++ b/mysql-test/r/count_distinct.result
@@ -94,3 +94,11 @@ count(distinct i)
2
drop table t1;
drop view v1;
+create table t1 (user_id char(64) character set utf8);
+insert t1 values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17);
+set @@tmp_table_size = 1024;
+select count(distinct user_id) from t1;
+count(distinct user_id)
+17
+drop table t1;
+set @@tmp_table_size = default;
diff --git a/mysql-test/t/count_distinct.test b/mysql-test/t/count_distinct.test
index 10b4ac6f0e7..ac97cdba357 100644
--- a/mysql-test/t/count_distinct.test
+++ b/mysql-test/t/count_distinct.test
@@ -107,3 +107,17 @@ create view v1 as select * from t1;
select count(distinct i) from v1;
drop table t1;
drop view v1;
+
+#
+# MDEV-12136 SELECT COUNT(DISTINCT) returns the wrong value when tmp_table_size is limited
+#
+create table t1 (user_id char(64) character set utf8);
+insert t1 values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17);
+set @@tmp_table_size = 1024;
+select count(distinct user_id) from t1;
+drop table t1;
+set @@tmp_table_size = default;
+
+#
+# End of 5.5 tests
+#
diff --git a/sql/uniques.cc b/sql/uniques.cc
index fe3e329cda6..f80117065dd 100644
--- a/sql/uniques.cc
+++ b/sql/uniques.cc
@@ -461,7 +461,7 @@ C_MODE_END
<> 0 error
*/
-static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
+static bool merge_walk(uchar *merge_buffer, size_t merge_buffer_size,
uint key_length, BUFFPEK *begin, BUFFPEK *end,
tree_walk_action walk_action, void *walk_action_arg,
qsort_cmp2 compare, void *compare_arg,
@@ -470,7 +470,7 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
BUFFPEK_COMPARE_CONTEXT compare_context = { compare, compare_arg };
QUEUE queue;
if (end <= begin ||
- merge_buffer_size < (ulong) (key_length * (end - begin + 1)) ||
+ merge_buffer_size < (size_t) (key_length * (end - begin + 1)) ||
init_queue(&queue, (uint) (end - begin), offsetof(BUFFPEK, key), 0,
buffpek_compare, &compare_context, 0, 0))
return 1;
@@ -615,7 +615,7 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg)
if (!res)
{
- res= merge_walk(merge_buffer, (ulong) max_in_memory_size, full_size,
+ res= merge_walk(merge_buffer, buff_sz, full_size,
(BUFFPEK *) file_ptrs.buffer,
(BUFFPEK *) file_ptrs.buffer + file_ptrs.elements,
action, walk_action_arg,
From 27bc13b7a2f99a6011a5081670b320c685dde443 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Wed, 12 Jul 2017 19:31:01 +0200
Subject: [PATCH 045/101] MDEV-12136 SELECT COUNT(DISTINCT) returns the wrong
value when tmp_table_size is limited
Same MDEV, second bug.
Merge buffer must fit at least MERGEBUFF2 (that is, 15) key values.
Because merge_index() can merge that many buffers, and
merge_many_buff() leaves that many buffers unmerged.
---
mysql-test/r/count_distinct.result | 4 ++++
mysql-test/t/count_distinct.test | 2 ++
sql/uniques.cc | 8 ++++++--
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/mysql-test/r/count_distinct.result b/mysql-test/r/count_distinct.result
index 3decd5f60bc..d55a232c715 100644
--- a/mysql-test/r/count_distinct.result
+++ b/mysql-test/r/count_distinct.result
@@ -100,5 +100,9 @@ set @@tmp_table_size = 1024;
select count(distinct user_id) from t1;
count(distinct user_id)
17
+alter table t1 modify user_id char(128) character set utf8;
+select count(distinct user_id) from t1;
+count(distinct user_id)
+17
drop table t1;
set @@tmp_table_size = default;
diff --git a/mysql-test/t/count_distinct.test b/mysql-test/t/count_distinct.test
index ac97cdba357..a00574b6cba 100644
--- a/mysql-test/t/count_distinct.test
+++ b/mysql-test/t/count_distinct.test
@@ -115,6 +115,8 @@ create table t1 (user_id char(64) character set utf8);
insert t1 values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17);
set @@tmp_table_size = 1024;
select count(distinct user_id) from t1;
+alter table t1 modify user_id char(128) character set utf8;
+select count(distinct user_id) from t1;
drop table t1;
set @@tmp_table_size = default;
diff --git a/sql/uniques.cc b/sql/uniques.cc
index f80117065dd..8b7da7e6e52 100644
--- a/sql/uniques.cc
+++ b/sql/uniques.cc
@@ -607,11 +607,15 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg)
return 1;
if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0))
return 1;
- size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size;
+ /*
+ merge_buffer must fit at least MERGEBUFF2 keys, because
+ merge_index() can merge that many BUFFPEKs at once.
+ */
+ size_t buff_sz= max(MERGEBUFF2, max_in_memory_size/full_size+1) * full_size;
if (!(merge_buffer = (uchar *)my_malloc(buff_sz, MYF(MY_WME))))
return 1;
if (buff_sz < (ulong) (full_size * (file_ptrs.elements + 1)))
- res= merge(table, merge_buffer, buff_sz >= full_size * MERGEBUFF2) ;
+ res= merge(table, merge_buffer, true) ;
if (!res)
{
From 7338d3f221e33042dfcf5c1a245317aa7cb015a7 Mon Sep 17 00:00:00 2001
From: Daniel Black
Date: Fri, 14 Jul 2017 13:37:37 +1000
Subject: [PATCH 046/101] client: mysql - fix type
field_names[x][y] is a pointer
client/mysql.cc: In function 'void build_completion_hash(bool, bool)':
client/mysql.cc:2855:37: error: invalid conversion from 'char' to 'char*' [-fpermissive]
field_names[i][num_fields*2]= '\0';
Signed-off-by: Daniel Black
---
client/mysql.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/client/mysql.cc b/client/mysql.cc
index a965ced89c6..ca586a5590f 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -2852,7 +2852,7 @@ You can turn off this feature to get a quicker startup with -A\n\n");
mysql_free_result(fields);
break;
}
- field_names[i][num_fields*2]= '\0';
+ field_names[i][num_fields*2]= NULL;
j=0;
while ((sql_field=mysql_fetch_field(fields)))
{
From c8c6a9fdf4ac3e506e52a80fe4a766d203178cce Mon Sep 17 00:00:00 2001
From: Daniel Black
Date: Mon, 8 May 2017 11:55:51 +1000
Subject: [PATCH 047/101] mtr: fix_vs_config doesn't change bindir
Signed-off-by: Daniel Black
---
mysql-test/mysql-test-run.pl | 4 ----
1 file changed, 4 deletions(-)
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 47c4f6ca737..750722ea5a5 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -1290,10 +1290,6 @@ sub command_line_setup {
fix_vs_config_dir();
- # Respect MTR_BINDIR variable, which is typically set in to the
- # build directory in out-of-source builds.
- $bindir=$ENV{MTR_BINDIR}||$basedir;
-
# Look for the client binaries directory
if ($path_client_bindir)
{
From 0375f2e2730c6e30f3e6f171c9b73d8553a3ae9a Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Fri, 14 Jul 2017 15:30:27 +0200
Subject: [PATCH 048/101] MDEV-12144 Signal 6 crash corrupts ibd files
Avoid using STDERR_FILENO. The server uses freopen(stderr),
so stderr can be on any file descriptor.
---
include/my_global.h | 5 ++---
mysys/my_fopen.c | 2 +-
mysys/stacktrace.c | 2 +-
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/include/my_global.h b/include/my_global.h
index 0c15478439f..42e3c1ad0c8 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -421,9 +421,8 @@ extern "C" int madvise(void *addr, size_t len, int behav);
#define SIGNAL_HANDLER_RESET_ON_DELIVERY
#endif
-#ifndef STDERR_FILENO
-#define STDERR_FILENO fileno(stderr)
-#endif
+/* don't assume that STDERR_FILENO is 2, mysqld can freopen */
+#undef STDERR_FILENO
/*
Deprecated workaround for false-positive uninitialized variables
diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c
index 99a9035c0c2..9131a2549e0 100644
--- a/mysys/my_fopen.c
+++ b/mysys/my_fopen.c
@@ -143,7 +143,7 @@ static int no_close(void *cookie __attribute__((unused)))
/*
A hack around a race condition in the implementation of freopen.
- The race condition steams from the fact that the current fd of
+ The race condition stems from the fact that the current fd of
the stream is closed before its number is used to duplicate the
new file descriptor. This defeats the desired atomicity of the
close and duplicate of dup2().
diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c
index 402520990b6..ae715c04621 100644
--- a/mysys/stacktrace.c
+++ b/mysys/stacktrace.c
@@ -744,7 +744,7 @@ void my_safe_print_str(const char *val, int len)
size_t my_write_stderr(const void *buf, size_t count)
{
- return (size_t) write(STDERR_FILENO, buf, count);
+ return (size_t) write(fileno(stderr), buf, count);
}
From ec4e39558ee33da4e10fb1afc6702f325e6aec30 Mon Sep 17 00:00:00 2001
From: Daniel Black
Date: Sun, 2 Jul 2017 17:02:03 +1000
Subject: [PATCH 049/101] ma_recovery: unintentional order of operations
Coverity report this as:
CID 971840 (#1 of 1): Operands don't affect result (CONSTANT_EXPRESSION_RESULT)
result_independent_of_operands: 4 | (flags & 1) is always true regardless of the values of its operands. This occurs as the logical first operand of "?:".
The C order of precidence has | of higher precidence than ?:. The
intenting implies an | of the 3 terms.
Adjust to intented meaning.
---
storage/maria/ma_recovery.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c
index 5e42ebc8d5d..618e6381f27 100644
--- a/storage/maria/ma_recovery.c
+++ b/storage/maria/ma_recovery.c
@@ -888,7 +888,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE)
goto end;
fn_format(filename, name, "", MARIA_NAME_IEXT,
(MY_UNPACK_FILENAME |
- (flags & HA_DONT_TOUCH_DATA) ? MY_RETURN_REAL_PATH : 0) |
+ ((flags & HA_DONT_TOUCH_DATA) ? MY_RETURN_REAL_PATH : 0)) |
MY_APPEND_EXT);
linkname_ptr= NULL;
create_flag= MY_DELETE_OLD;
From 6efee2254110206a037bb726de00a4e734ae8453 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Fri, 14 Jul 2017 19:08:59 +0200
Subject: [PATCH 050/101] change flags as it was done in MyISAM
in ab785bfe5b50
---
storage/maria/ma_recovery.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c
index 618e6381f27..b2e8705b15e 100644
--- a/storage/maria/ma_recovery.c
+++ b/storage/maria/ma_recovery.c
@@ -887,9 +887,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE)
if (create_database_if_not_exists(name))
goto end;
fn_format(filename, name, "", MARIA_NAME_IEXT,
- (MY_UNPACK_FILENAME |
- ((flags & HA_DONT_TOUCH_DATA) ? MY_RETURN_REAL_PATH : 0)) |
- MY_APPEND_EXT);
+ MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH | MY_APPEND_EXT);
linkname_ptr= NULL;
create_flag= MY_DELETE_OLD;
tprint(tracef, "Table '%s' creating as '%s'\n", name, filename);
From 2f07709aed863ea1852a78a0d6ab718e49df8cca Mon Sep 17 00:00:00 2001
From: Daniel Black
Date: Sun, 16 Jul 2017 02:45:37 +1000
Subject: [PATCH 051/101] MDEV-12436: binlog.binlog_unsafe - assumed
len(hostname) <= 50 (#385)
Increased size in tests to allow for 100 character hostname.
Signed-off-by: Daniel Black
---
.../suite/binlog/r/binlog_unsafe.result | 22 +++++++++----------
mysql-test/suite/binlog/t/binlog_unsafe.test | 22 +++++++++----------
2 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result
index 5b6adf5600e..48d9db44b05 100644
--- a/mysql-test/suite/binlog/r/binlog_unsafe.result
+++ b/mysql-test/suite/binlog/r/binlog_unsafe.result
@@ -1,14 +1,14 @@
#### Setup tables ####
-CREATE TABLE t0 (a CHAR(100));
-CREATE TABLE t1 (a CHAR(100));
-CREATE TABLE t2 (a CHAR(100));
-CREATE TABLE t3 (a CHAR(100));
-CREATE TABLE ta0 (a CHAR(100));
-CREATE TABLE ta1 (a CHAR(100));
-CREATE TABLE ta2 (a CHAR(100));
-CREATE TABLE ta3 (a CHAR(100));
+CREATE TABLE t0 (a CHAR(200));
+CREATE TABLE t1 (a CHAR(200));
+CREATE TABLE t2 (a CHAR(200));
+CREATE TABLE t3 (a CHAR(200));
+CREATE TABLE ta0 (a CHAR(200));
+CREATE TABLE ta1 (a CHAR(200));
+CREATE TABLE ta2 (a CHAR(200));
+CREATE TABLE ta3 (a CHAR(200));
CREATE TABLE autoinc_table (a INT PRIMARY KEY AUTO_INCREMENT);
-CREATE TABLE data_table (a CHAR(100));
+CREATE TABLE data_table (a CHAR(200));
INSERT INTO data_table VALUES ('foo');
CREATE TABLE trigger_table_1 (a INT);
CREATE TABLE trigger_table_2 (a INT);
@@ -2392,7 +2392,7 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc
DROP PROCEDURE p1;
DROP TABLE t1;
DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (a VARCHAR(100), b VARCHAR(100));
+CREATE TABLE t1 (a VARCHAR(200), b VARCHAR(200));
INSERT INTO t1 VALUES ('a','b');
UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1;
Warnings:
@@ -2423,7 +2423,7 @@ CREATE FUNCTION fun_check_log_bin() RETURNS INT
BEGIN
SET @@SQL_LOG_BIN = 0;
INSERT INTO t1 VALUES(@@global.sync_binlog);
-RETURN 100;
+RETURN 200;
END|
"One unsafe warning should be issued in the following statement"
SELECT fun_check_log_bin();
diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test
index 2de84a58875..aaf4697b91f 100644
--- a/mysql-test/suite/binlog/t/binlog_unsafe.test
+++ b/mysql-test/suite/binlog/t/binlog_unsafe.test
@@ -110,16 +110,16 @@ call mtr.add_suppression("Unsafe statement written to the binary log using state
--echo #### Setup tables ####
-CREATE TABLE t0 (a CHAR(100));
-CREATE TABLE t1 (a CHAR(100));
-CREATE TABLE t2 (a CHAR(100));
-CREATE TABLE t3 (a CHAR(100));
-CREATE TABLE ta0 (a CHAR(100));
-CREATE TABLE ta1 (a CHAR(100));
-CREATE TABLE ta2 (a CHAR(100));
-CREATE TABLE ta3 (a CHAR(100));
+CREATE TABLE t0 (a CHAR(200));
+CREATE TABLE t1 (a CHAR(200));
+CREATE TABLE t2 (a CHAR(200));
+CREATE TABLE t3 (a CHAR(200));
+CREATE TABLE ta0 (a CHAR(200));
+CREATE TABLE ta1 (a CHAR(200));
+CREATE TABLE ta2 (a CHAR(200));
+CREATE TABLE ta3 (a CHAR(200));
CREATE TABLE autoinc_table (a INT PRIMARY KEY AUTO_INCREMENT);
-CREATE TABLE data_table (a CHAR(100));
+CREATE TABLE data_table (a CHAR(200));
INSERT INTO data_table VALUES ('foo');
CREATE TABLE trigger_table_1 (a INT);
CREATE TABLE trigger_table_2 (a INT);
@@ -433,7 +433,7 @@ DROP TABLE t1;
DROP TABLE IF EXISTS t1;
--enable_warnings
-CREATE TABLE t1 (a VARCHAR(100), b VARCHAR(100));
+CREATE TABLE t1 (a VARCHAR(200), b VARCHAR(200));
INSERT INTO t1 VALUES ('a','b');
UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1;
DROP TABLE t1;
@@ -471,7 +471,7 @@ CREATE FUNCTION fun_check_log_bin() RETURNS INT
BEGIN
SET @@SQL_LOG_BIN = 0;
INSERT INTO t1 VALUES(@@global.sync_binlog);
- RETURN 100;
+ RETURN 200;
END|
DELIMITER ;|
--echo "One unsafe warning should be issued in the following statement"
From d023156782ce37f508c121437b8b3544fb03ef14 Mon Sep 17 00:00:00 2001
From: Alexander Barkov
Date: Fri, 30 Oct 2015 10:10:43 +0400
Subject: [PATCH 052/101] MDEV-8692 prefschema test failures on ARM (on Debian
build system)
A few tests assumes that the CYCLE timer is always available,
which is not true on some platforms (e.g. ARM).
Fixing the tests not to reply on the CYCLE availability.
---
.../perfschema/include/have_timer_cycle.inc | 4 +++
.../suite/perfschema/r/privilege.result | 8 +++---
.../perfschema/t/dml_performance_timers.test | 1 +
.../suite/perfschema/t/dml_setup_timers.test | 1 +
mysql-test/suite/perfschema/t/privilege.test | 14 ++++++++---
mysys/my_rdtsc.c | 25 +++++++++++++++++++
6 files changed, 47 insertions(+), 6 deletions(-)
create mode 100644 mysql-test/suite/perfschema/include/have_timer_cycle.inc
diff --git a/mysql-test/suite/perfschema/include/have_timer_cycle.inc b/mysql-test/suite/perfschema/include/have_timer_cycle.inc
new file mode 100644
index 00000000000..b801ea256d6
--- /dev/null
+++ b/mysql-test/suite/perfschema/include/have_timer_cycle.inc
@@ -0,0 +1,4 @@
+if (!`SELECT count(*) FROM performance_schema.performance_timers WHERE timer_name='CYCLE' AND timer_frequency IS NOT NULL`)
+{
+ Skip Need performance timer CYCLE;
+}
diff --git a/mysql-test/suite/perfschema/r/privilege.result b/mysql-test/suite/perfschema/r/privilege.result
index d1831c9c4be..61eade13bbf 100644
--- a/mysql-test/suite/perfschema/r/privilege.result
+++ b/mysql-test/suite/perfschema/r/privilege.result
@@ -554,7 +554,7 @@ ERROR 42000: DROP command denied to user 'pfs_user_4'@'localhost' for table 'eve
#
# Grant access to change tables with the root account
GRANT UPDATE ON performance_schema.setup_consumers TO pfs_user_4;
-GRANT UPDATE ON performance_schema.setup_timers TO pfs_user_4;
+GRANT UPDATE, SELECT ON performance_schema.setup_timers TO pfs_user_4;
GRANT UPDATE, SELECT ON performance_schema.setup_instruments TO pfs_user_4;
GRANT DROP ON performance_schema.events_waits_current TO pfs_user_4;
GRANT DROP ON performance_schema.events_waits_history TO pfs_user_4;
@@ -565,7 +565,7 @@ UPDATE performance_schema.setup_instruments SET enabled = 'YES'
WHERE name LIKE 'wait/synch/mutex/%'
OR name LIKE 'wait/synch/rwlock/%';
UPDATE performance_schema.setup_consumers SET enabled = 'YES';
-UPDATE performance_schema.setup_timers SET timer_name = 'TICK';
+UPDATE performance_schema.setup_timers SET timer_name = 'TICK' WHERE name <> "wait";
TRUNCATE TABLE performance_schema.events_waits_history_long;
TRUNCATE TABLE performance_schema.events_waits_history;
TRUNCATE TABLE performance_schema.events_waits_current;
@@ -575,4 +575,6 @@ DROP USER pfs_user_4;
flush privileges;
UPDATE performance_schema.setup_instruments SET enabled = 'YES', timed = 'YES';
UPDATE performance_schema.setup_consumers SET enabled = 'YES';
-UPDATE performance_schema.setup_timers SET timer_name = 'CYCLE';
+UPDATE performance_schema.setup_timers SET timer_name = 'MICROSECOND' where name="idle";
+UPDATE performance_schema.setup_timers SET timer_name = 'NANOSECOND' where name="stage";
+UPDATE performance_schema.setup_timers SET timer_name = 'NANOSECOND' where name="statement";
diff --git a/mysql-test/suite/perfschema/t/dml_performance_timers.test b/mysql-test/suite/perfschema/t/dml_performance_timers.test
index 2ec37fbe7e9..587c54144aa 100644
--- a/mysql-test/suite/perfschema/t/dml_performance_timers.test
+++ b/mysql-test/suite/perfschema/t/dml_performance_timers.test
@@ -2,6 +2,7 @@
--source include/not_embedded.inc
--source include/have_perfschema.inc
+--source include/have_timer_cycle.inc
--replace_column 2 3 4
select * from performance_schema.performance_timers;
diff --git a/mysql-test/suite/perfschema/t/dml_setup_timers.test b/mysql-test/suite/perfschema/t/dml_setup_timers.test
index 0956ae2cc95..6a6b813ab07 100644
--- a/mysql-test/suite/perfschema/t/dml_setup_timers.test
+++ b/mysql-test/suite/perfschema/t/dml_setup_timers.test
@@ -2,6 +2,7 @@
--source include/not_embedded.inc
--source include/have_perfschema.inc
+--source include/have_timer_cycle.inc
select * from performance_schema.setup_timers;
diff --git a/mysql-test/suite/perfschema/t/privilege.test b/mysql-test/suite/perfschema/t/privilege.test
index 3b4cd1a4d2b..47a68602fa4 100644
--- a/mysql-test/suite/perfschema/t/privilege.test
+++ b/mysql-test/suite/perfschema/t/privilege.test
@@ -291,7 +291,7 @@ TRUNCATE TABLE performance_schema.events_waits_current;
--echo # Grant access to change tables with the root account
GRANT UPDATE ON performance_schema.setup_consumers TO pfs_user_4;
-GRANT UPDATE ON performance_schema.setup_timers TO pfs_user_4;
+GRANT UPDATE, SELECT ON performance_schema.setup_timers TO pfs_user_4;
GRANT UPDATE, SELECT ON performance_schema.setup_instruments TO pfs_user_4;
GRANT DROP ON performance_schema.events_waits_current TO pfs_user_4;
GRANT DROP ON performance_schema.events_waits_history TO pfs_user_4;
@@ -308,7 +308,11 @@ WHERE name LIKE 'wait/synch/mutex/%'
UPDATE performance_schema.setup_consumers SET enabled = 'YES';
-UPDATE performance_schema.setup_timers SET timer_name = 'TICK';
+# We do not touch "wait", to avoid restoring it at the end of the test,
+# as its default value initialized at server startup is ambiguous:
+# it can be CYCLE or NANOSECOND depending on platform
+
+UPDATE performance_schema.setup_timers SET timer_name = 'TICK' WHERE name <> "wait";
TRUNCATE TABLE performance_schema.events_waits_history_long;
TRUNCATE TABLE performance_schema.events_waits_history;
@@ -323,5 +327,9 @@ DROP USER pfs_user_4;
flush privileges;
UPDATE performance_schema.setup_instruments SET enabled = 'YES', timed = 'YES';
UPDATE performance_schema.setup_consumers SET enabled = 'YES';
-UPDATE performance_schema.setup_timers SET timer_name = 'CYCLE';
+# Restore the default values for the timers that we changed.
+# Note, we did not touch "wait", see above.
+UPDATE performance_schema.setup_timers SET timer_name = 'MICROSECOND' where name="idle";
+UPDATE performance_schema.setup_timers SET timer_name = 'NANOSECOND' where name="stage";
+UPDATE performance_schema.setup_timers SET timer_name = 'NANOSECOND' where name="statement";
diff --git a/mysys/my_rdtsc.c b/mysys/my_rdtsc.c
index 028c7f810d4..ad11e8c6a6c 100644
--- a/mysys/my_rdtsc.c
+++ b/mysys/my_rdtsc.c
@@ -129,6 +129,31 @@ ulonglong my_timer_cycles_il_x86_64();
clock_gettime(CLOCK_SGI_CYCLE) for Irix platforms,
or on read_real_time for aix platforms. There is
nothing for Alpha platforms, they would be tricky.
+
+ On the platforms that do not have a CYCLE timer,
+ "wait" events are initialized to use NANOSECOND instead of CYCLE
+ during performance_schema initialization (at the server startup).
+
+ Linux performance monitor (see "man perf_event_open") can
+ provide cycle counter on the platforms that do not have
+ other kinds of cycle counters. But we don't use it so far.
+
+ ARM notes
+ ---------
+ During tests on ARMv7 Debian, perf_even_open() based cycle counter provided
+ too low frequency with too high overhead:
+ MariaDB [performance_schema]> SELECT * FROM performance_timers;
+ +-------------+-----------------+------------------+----------------+
+ | TIMER_NAME | TIMER_FREQUENCY | TIMER_RESOLUTION | TIMER_OVERHEAD |
+ +-------------+-----------------+------------------+----------------+
+ | CYCLE | 689368159 | 1 | 970 |
+ | NANOSECOND | 1000000000 | 1 | 308 |
+ | MICROSECOND | 1000000 | 1 | 417 |
+ | MILLISECOND | 1000 | 1000 | 407 |
+ | TICK | 127 | 1 | 612 |
+ +-------------+-----------------+------------------+----------------+
+ Therefore, it was decided not to use perf_even_open() on ARM
+ (i.e. go without CYCLE and have "wait" events use NANOSECOND by default).
*/
ulonglong my_timer_cycles(void)
From 7d309b5f74982861efdfd069fd0e46c18d0cb7fe Mon Sep 17 00:00:00 2001
From: Elena Stepanova
Date: Tue, 18 Jul 2017 01:38:13 +0300
Subject: [PATCH 053/101] Add storage_engine/parts overlay for MyISAM
---
storage/myisam/mysql-test/storage_engine/parts/disabled.def | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 storage/myisam/mysql-test/storage_engine/parts/disabled.def
diff --git a/storage/myisam/mysql-test/storage_engine/parts/disabled.def b/storage/myisam/mysql-test/storage_engine/parts/disabled.def
new file mode 100644
index 00000000000..e69de29bb2d
From c9883b75914d0ba4975aae0fbf8164f026e88559 Mon Sep 17 00:00:00 2001
From: Daniel Black
Date: Sun, 2 Jul 2017 14:53:23 +1000
Subject: [PATCH 054/101] ma_check/mi_check: maria_repair_parallel
initialization for !quick
end_io_call uses uninitialized values from the new_data_cache
As such we the buffer 0 and check this before calling end_io_cache on it.
Thanks Sergey Vojtovich for the review and for this solution.
Found by Coverity (ref 972481).
---
storage/maria/ma_check.c | 4 +++-
storage/myisam/mi_check.c | 4 +++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index fb35edc3be3..198df72a1d6 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -4250,6 +4250,8 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
}
*/
DBUG_PRINT("info", ("is quick repair: %d", (int) rep_quick));
+ if (!rep_quick)
+ my_b_clear(&new_data_cache);
/* Initialize pthread structures before goto err. */
mysql_mutex_init(key_SORT_INFO_mutex, &sort_info.mutex, MY_MUTEX_INIT_FAST);
@@ -4608,7 +4610,7 @@ err:
already or they were not yet started (if the error happend before
creating the threads).
*/
- if (!rep_quick)
+ if (!rep_quick && my_b_inited(&new_data_cache))
end_io_cache(&new_data_cache);
if (!got_error)
{
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index df97d6035d8..23e54966e2d 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -2676,6 +2676,8 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
*/
DBUG_PRINT("info", ("is quick repair: %d", rep_quick));
bzero((char*)&sort_info,sizeof(sort_info));
+ if (!rep_quick)
+ my_b_clear(&new_data_cache);
/* Initialize pthread structures before goto err. */
mysql_mutex_init(mi_key_mutex_MI_SORT_INFO_mutex,
&sort_info.mutex, MY_MUTEX_INIT_FAST);
@@ -3050,7 +3052,7 @@ err:
already or they were not yet started (if the error happend before
creating the threads).
*/
- if (!rep_quick)
+ if (!rep_quick && my_b_inited(&new_data_cache))
(void) end_io_cache(&new_data_cache);
if (!got_error)
{
From 7e44eabdad59993c504699e01d15ddb106f64e9b Mon Sep 17 00:00:00 2001
From: Alexey Botchkov
Date: Tue, 18 Jul 2017 13:19:34 +0400
Subject: [PATCH 055/101] MDEV-11205 UDF_ARGS "attribute_lengths" incorrect
value.
Set name_length properly in Item_idnet constructors.
---
sql/item.cc | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sql/item.cc b/sql/item.cc
index b7dac96d418..dff2f3d3ee6 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -817,6 +817,7 @@ Item_ident::Item_ident(Name_resolution_context *context_arg,
cached_table(0), depended_from(0), can_be_depended(TRUE)
{
name = (char*) field_name_arg;
+ name_length= name ? strlen(name) : 0;
}
@@ -829,6 +830,7 @@ Item_ident::Item_ident(TABLE_LIST *view_arg, const char *field_name_arg)
cached_table(NULL), depended_from(NULL), can_be_depended(TRUE)
{
name = (char*) field_name_arg;
+ name_length= name ? strlen(name) : 0;
}
From e7fd6ed3875bd91dbd30a62291ae471c35da8fdf Mon Sep 17 00:00:00 2001
From: Oleksandr Byelkin
Date: Mon, 17 Jul 2017 22:34:07 +0200
Subject: [PATCH 056/101] MDEV-11240: Server crashes in
check_view_single_update or Assertion `derived->table' failed in
mysql_derived_merge_for_insert
Move table pointer for single table view (even if it is view over other view) to make the access universal.
---
mysql-test/r/view.result | 14 ++++++++++++++
mysql-test/t/view.test | 16 ++++++++++++++++
sql/sql_derived.cc | 4 +++-
3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 414de5662f3..0f8e9999730 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -5618,6 +5618,20 @@ Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(((`test`.`t2`.`c` = `test`.`t1`.`b`) and (`test`.`t3`.`f` = `test`.`t1`.`a`) and (`test`.`t2`.`d` = `test`.`t3`.`e`) and (`test`.`t1`.`a` is not null) and (`test`.`t1`.`a` is not null) and (`test`.`t1`.`b` is not null))) where (`test`.`t1`.`a` < 5)
drop view v1;
drop table t1,t2,t3;
+#
+# MDEV-11240: Server crashes in check_view_single_update or
+# Assertion `derived->table' failed in mysql_derived_merge_for_insert
+#
+CREATE TABLE t3 (a INT);
+CREATE ALGORITHM = MERGE VIEW v1 AS SELECT t2.a FROM t3 AS t1, t3 AS t2;
+CREATE ALGORITHM = MERGE VIEW v2 AS SELECT * FROM v1;
+PREPARE stmt FROM 'REPLACE INTO v2 SELECT a FROM t3';
+EXECUTE stmt;
+ERROR HY000: Can not insert into join view 'test.v2' without fields list
+EXECUTE stmt;
+ERROR HY000: Can not insert into join view 'test.v2' without fields list
+drop view v1,v2;
+drop table t3;
# -----------------------------------------------------------------
# -- End of 5.5 tests.
# -----------------------------------------------------------------
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index aece2000cd4..659327eebb1 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -5565,6 +5565,22 @@ select *
drop view v1;
drop table t1,t2,t3;
+--echo #
+--echo # MDEV-11240: Server crashes in check_view_single_update or
+--echo # Assertion `derived->table' failed in mysql_derived_merge_for_insert
+--echo #
+
+CREATE TABLE t3 (a INT);
+CREATE ALGORITHM = MERGE VIEW v1 AS SELECT t2.a FROM t3 AS t1, t3 AS t2;
+CREATE ALGORITHM = MERGE VIEW v2 AS SELECT * FROM v1;
+PREPARE stmt FROM 'REPLACE INTO v2 SELECT a FROM t3';
+--error ER_VIEW_NO_INSERT_FIELD_LIST
+EXECUTE stmt;
+--error ER_VIEW_NO_INSERT_FIELD_LIST
+EXECUTE stmt;
+drop view v1,v2;
+drop table t3;
+
--echo # -----------------------------------------------------------------
--echo # -- End of 5.5 tests.
--echo # -----------------------------------------------------------------
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 20fca2de8cf..493f0eccc8c 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -525,7 +525,9 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
derived->schema_table= derived->merge_underlying_list->schema_table;
derived->merged_for_insert= TRUE;
}
- }
+ }
+ else
+ derived->table= derived->merge_underlying_list->table;
DBUG_RETURN(FALSE);
}
From f6bcdb9e3c955f0a998a996edd93362deca31edf Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Tue, 18 Jul 2017 14:45:44 +0200
Subject: [PATCH 057/101] test case for loadxml and spaces
---
mysql-test/r/loadxml.result | 16 ++++++++--------
mysql-test/std_data/loadxml.dat | 8 ++++----
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/mysql-test/r/loadxml.result b/mysql-test/r/loadxml.result
index 1128caf9122..250037f60b8 100644
--- a/mysql-test/r/loadxml.result
+++ b/mysql-test/r/loadxml.result
@@ -5,10 +5,10 @@ load xml infile '../../std_data/loadxml.dat' into table t1
rows identified by '';
select * from t1 order by a;
a b
-1 b1
-2 b2
-3 b3
-11 b11
+1 b1
+2 b2
+3 b3
+11 b11
111 b111
112 b112 & < > " ' &unknown; -- check entities
212 b212
@@ -81,17 +81,17 @@ LOAD XML INFILE '../../std_data/loadxml.dat' INTO TABLE t1
ROWS IDENTIFIED BY '' (a,@b) SET b=concat('!',@b);
SELECT * FROM t1 ORDER BY a;
a b
-1 !b1
-11 !b11
+1 ! b1
+11 ! b11
111 !b111
112 !b112 & < > " ' &unknown; -- check entities
-2 !b2
+2 ! b2
212 !b212
213 !b213
214 !b214
215 !b215
216 !&bb b;
-3 !b3
+3 ! b3
DROP TABLE t1;
#
# Bug#16171518 LOAD XML DOES NOT HANDLE EMPTY ELEMENTS
diff --git a/mysql-test/std_data/loadxml.dat b/mysql-test/std_data/loadxml.dat
index b72fac9da74..d5ccd4a1b13 100644
--- a/mysql-test/std_data/loadxml.dat
+++ b/mysql-test/std_data/loadxml.dat
@@ -9,19 +9,19 @@
1
- b1
+ b1
2
- b2
+ b2
3
- b3
+ b3
11
- b11
+ b11
From 9b3360ea4417ed653d5c7eed29f4ef7e80618e43 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Tue, 18 Jul 2017 14:47:40 +0200
Subject: [PATCH 058/101] BUG#25250768: WRITING ON A READ_ONLY=ON SERVER
WITHOUT SUPER PRIVILEGE
simplify.
add a test case.
---
mysql-test/r/read_only.result | 2 ++
mysql-test/t/read_only.test | 3 +++
sql/sql_parse.cc | 26 +++++++++-----------------
3 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/mysql-test/r/read_only.result b/mysql-test/r/read_only.result
index 1ffe2b86f70..807dc426696 100644
--- a/mysql-test/r/read_only.result
+++ b/mysql-test/r/read_only.result
@@ -30,6 +30,8 @@ create temporary table t3 (a int);
create temporary table t4 (a int) select * from t3;
insert into t3 values(1);
insert into t4 select * from t3;
+create table t3 (a int);
+ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a;
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
update t1,t3 set t3.a=t1.a+1 where t1.a=t3.a;
diff --git a/mysql-test/t/read_only.test b/mysql-test/t/read_only.test
index 52349747883..a0bd7b49273 100644
--- a/mysql-test/t/read_only.test
+++ b/mysql-test/t/read_only.test
@@ -80,6 +80,9 @@ insert into t3 values(1);
insert into t4 select * from t3;
+--error ER_OPTION_PREVENTS_STATEMENT
+create table t3 (a int);
+
# a non-temp table updated:
--error ER_OPTION_PREVENTS_STATEMENT
update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 83cd6cccba5..1d596ed9df7 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -835,24 +835,16 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
if (lex->sql_command == SQLCOM_UPDATE_MULTI)
DBUG_RETURN(FALSE);
- const my_bool create_temp_tables=
- (lex->sql_command == SQLCOM_CREATE_TABLE) &&
- (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE);
+ /*
+ a table-to-be-created is not in the temp table list yet,
+ so CREATE TABLE needs a special treatment
+ */
+ const bool update_real_tables=
+ lex->sql_command == SQLCOM_CREATE_TABLE
+ ? !(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
+ : some_non_temp_table_to_be_updated(thd, all_tables);
- const my_bool create_real_tables=
- (lex->sql_command == SQLCOM_CREATE_TABLE) &&
- !(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE);
-
- const my_bool drop_temp_tables=
- (lex->sql_command == SQLCOM_DROP_TABLE) &&
- lex->drop_temporary;
-
- const my_bool update_real_tables=
- ((create_real_tables ||
- some_non_temp_table_to_be_updated(thd, all_tables)) &&
- !(create_temp_tables || drop_temp_tables));
-
- const my_bool create_or_drop_databases=
+ const bool create_or_drop_databases=
(lex->sql_command == SQLCOM_CREATE_DB) ||
(lex->sql_command == SQLCOM_DROP_DB);
From 7c9d00e0bb1977e474dff28c2ce93f27599bbc10 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Tue, 18 Jul 2017 14:48:25 +0200
Subject: [PATCH 059/101] Bug #24595639: INCORRECT BEHAVIOR IN QUERY WITH UNION
AND GROUP BY
test case
---
mysql-test/r/union.result | 18 ++++++++++++++++++
mysql-test/t/union.test | 15 +++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 5a6cd8907e9..fe2339db471 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -1978,3 +1978,21 @@ d
2016-06-04 00:00:00
drop table t1;
End of 5.0 tests
+create table t1 (a int, b int);
+insert into t1 values (1,1),(2,2),(3,3);
+create table t2 (c varchar(30), d varchar(30));
+insert into t1 values ('1','1'),('2','2'),('4','4');
+create table t3 (e int, f int);
+insert into t3 values (1,1),(2,2),(31,31),(32,32);
+select e,f, (e , f) in (select e,b from t1 union select c,d from t2) as sub from t3;
+e f sub
+1 1 1
+2 2 1
+31 31 0
+32 32 0
+select avg(f), (e , f) in (select e,b from t1 union select c,d from t2) as sub from t3 group by sub;
+avg(f) sub
+31.5000 0
+1.5000 1
+drop table t1,t2,t3;
+End of 5.5 tests
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index f4dc6a5d449..4a3c19b49ab 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -1370,3 +1370,18 @@ order by d;
drop table t1;
--echo End of 5.0 tests
+
+#
+# Bug #24595639: INCORRECT BEHAVIOR IN QUERY WITH UNION AND GROUP BY
+#
+create table t1 (a int, b int);
+insert into t1 values (1,1),(2,2),(3,3);
+create table t2 (c varchar(30), d varchar(30));
+insert into t1 values ('1','1'),('2','2'),('4','4');
+create table t3 (e int, f int);
+insert into t3 values (1,1),(2,2),(31,31),(32,32);
+select e,f, (e , f) in (select e,b from t1 union select c,d from t2) as sub from t3;
+select avg(f), (e , f) in (select e,b from t1 union select c,d from t2) as sub from t3 group by sub;
+drop table t1,t2,t3;
+
+--echo End of 5.5 tests
From f9dbfa58a564262a5c696b0635c8186ecd84eeea Mon Sep 17 00:00:00 2001
From: Daniel Black
Date: Wed, 15 Mar 2017 08:33:46 +1100
Subject: [PATCH 060/101] MDEV-658: debian debug symbols require compat 9
Signed-off-by: Daniel Black
---
debian/compat | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/debian/compat b/debian/compat
index 7ed6ff82de6..ec635144f60 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-5
+9
From 172e3a1bc6ab1e38dd8be074b2c10cc734456e35 Mon Sep 17 00:00:00 2001
From: Daniel Black
Date: Mon, 1 May 2017 18:34:11 +1000
Subject: [PATCH 061/101] MDEV-12646: Apply fixes found by Coverity static
analysis tool
Inspired by: https://github.com/devexp-db/mariadb/blob/f27/mariadb-covscan-stroverflow.patch
---
plugin/semisync/semisync_master.cc | 6 +++---
sql/rpl_handler.cc | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/plugin/semisync/semisync_master.cc b/plugin/semisync/semisync_master.cc
index 3c22bcb94f2..16e6b091ca8 100644
--- a/plugin/semisync/semisync_master.cc
+++ b/plugin/semisync/semisync_master.cc
@@ -552,7 +552,7 @@ int ReplSemiSyncMaster::reportReplyBinlog(uint32 server_id,
if (need_copy_send_pos)
{
- strcpy(reply_file_name_, log_file_name);
+ strmake_buf(reply_file_name_, log_file_name);
reply_file_pos_ = log_file_pos;
reply_file_name_inited_ = true;
@@ -659,7 +659,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
if (cmp <= 0)
{
/* This thd has a lower position, let's update the minimum info. */
- strcpy(wait_file_name_, trx_wait_binlog_name);
+ strmake_buf(wait_file_name_, trx_wait_binlog_name);
wait_file_pos_ = trx_wait_binlog_pos;
rpl_semi_sync_master_wait_pos_backtraverse++;
@@ -670,7 +670,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
}
else
{
- strcpy(wait_file_name_, trx_wait_binlog_name);
+ strmake_buf(wait_file_name_, trx_wait_binlog_name);
wait_file_pos_ = trx_wait_binlog_pos;
wait_file_name_inited_ = true;
diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc
index 5b75d6c30ea..ca3b57edce3 100644
--- a/sql/rpl_handler.cc
+++ b/sql/rpl_handler.cc
@@ -260,7 +260,7 @@ int Binlog_storage_delegate::after_flush(THD *thd,
thd->semisync_info= log_info;
}
- strcpy(log_info->log_file, log_file+dirname_length(log_file));
+ strmake_buf(log_info->log_file, log_file+dirname_length(log_file));
log_info->log_pos = log_pos;
FOREACH_OBSERVER(ret, after_flush, false,
From 58aaae6f2a23e68b23727016844d177f178ea8ff Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Tue, 18 Jul 2017 16:42:40 +0200
Subject: [PATCH 062/101] ensure that filename in COM_BINLOG_DUMP isn't too
long
---
sql/sql_parse.cc | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1d596ed9df7..ba0520de4bb 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1271,9 +1271,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
kill_zombie_dump_threads(slave_server_id);
thd->server_id = slave_server_id;
- general_log_print(thd, command, "Log: '%s' Pos: %ld", packet+10,
- (long) pos);
- mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags);
+ const char *name= packet + 10;
+ size_t nlen= strlen(name);
+
+ general_log_print(thd, command, "Log: '%s' Pos: %lu", name, pos);
+ if (nlen < FN_REFLEN)
+ mysql_binlog_send(thd, thd->strmake(name, nlen), (my_off_t)pos, flags);
unregister_slave(thd,1,1);
/* fake COM_QUIT -- if we get here, the thread needs to terminate */
error = TRUE;
From 46977e0a01ae2118df08c3cccaf2f0eaaabd2715 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Tue, 18 Jul 2017 19:47:01 +0200
Subject: [PATCH 063/101] 5.5.55-38.8
---
storage/xtradb/btr/btr0btr.c | 2 +-
storage/xtradb/dict/dict0crea.c | 10 +-
storage/xtradb/dict/dict0load.c | 10 +-
storage/xtradb/dict/dict0mem.c | 2 +-
storage/xtradb/fil/fil0fil.c | 2 +-
storage/xtradb/fsp/fsp0fsp.c | 7 +-
storage/xtradb/handler/i_s.cc | 24 +----
storage/xtradb/include/btr0cur.h | 13 +--
storage/xtradb/include/btr0sea.h | 7 +-
storage/xtradb/include/buf0buddy.ic | 2 +-
storage/xtradb/include/buf0buf.h | 3 +-
storage/xtradb/include/dict0dict.h | 16 +--
storage/xtradb/include/dict0mem.h | 2 +-
storage/xtradb/include/dyn0dyn.h | 18 ++--
storage/xtradb/include/dyn0dyn.ic | 2 +-
storage/xtradb/include/fsp0fsp.h | 2 +-
storage/xtradb/include/log0online.h | 20 ++--
storage/xtradb/include/mach0data.h | 16 +--
storage/xtradb/include/mtr0mtr.h | 5 +-
storage/xtradb/include/os0file.h | 5 +-
storage/xtradb/include/page0page.h | 18 ++--
storage/xtradb/include/page0zip.h | 5 +-
storage/xtradb/include/rem0rec.h | 3 +-
storage/xtradb/include/row0upd.h | 5 +-
storage/xtradb/include/trx0trx.h | 4 +-
storage/xtradb/include/univ.i | 2 +-
storage/xtradb/log/log0online.c | 148 ++++++++++++++++++++--------
storage/xtradb/mach/mach0data.c | 48 ++++++---
storage/xtradb/os/os0file.c | 49 +++------
storage/xtradb/rem/rem0rec.c | 2 +-
storage/xtradb/row/row0merge.c | 4 +-
storage/xtradb/row/row0purge.c | 2 +-
storage/xtradb/srv/srv0srv.c | 9 +-
storage/xtradb/srv/srv0start.c | 2 +
storage/xtradb/trx/trx0roll.c | 4 +
35 files changed, 257 insertions(+), 216 deletions(-)
diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c
index 0c429363789..da848b1b4f8 100644
--- a/storage/xtradb/btr/btr0btr.c
+++ b/storage/xtradb/btr/btr0btr.c
@@ -2958,7 +2958,7 @@ Removes a page from the level list of pages.
/*************************************************************//**
Removes a page from the level list of pages. */
-static __attribute__((nonnull))
+static
void
btr_level_list_remove_func(
/*=======================*/
diff --git a/storage/xtradb/dict/dict0crea.c b/storage/xtradb/dict/dict0crea.c
index b950c2d9b3f..673bafacf31 100644
--- a/storage/xtradb/dict/dict0crea.c
+++ b/storage/xtradb/dict/dict0crea.c
@@ -112,13 +112,13 @@ dict_create_sys_tables_tuple(
dfield = dtuple_get_nth_field(entry, 3/*TYPE*/);
ptr = mem_heap_alloc(heap, 4);
- if (table->flags & (~DICT_TF_COMPACT & ~(~0 << DICT_TF_BITS))) {
+ if (table->flags & (~DICT_TF_COMPACT & ~(~0U << DICT_TF_BITS))) {
ut_a(table->flags & DICT_TF_COMPACT);
ut_a(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
ut_a((table->flags & DICT_TF_ZSSIZE_MASK)
<= (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT));
- ut_a(!(table->flags & (~0 << DICT_TF2_BITS)));
- mach_write_to_4(ptr, table->flags & ~(~0 << DICT_TF_BITS));
+ ut_a(!(table->flags & (~0U << DICT_TF2_BITS)));
+ mach_write_to_4(ptr, table->flags & ~(~0U << DICT_TF_BITS));
} else {
mach_write_to_4(ptr, DICT_TABLE_ORDINARY);
}
@@ -306,7 +306,7 @@ dict_build_table_def_step(
ut_ad(!dict_table_zip_size(table)
|| dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
- flags = table->flags & ~(~0 << DICT_TF_BITS);
+ flags = table->flags & ~(~0U << DICT_TF_BITS);
error = fil_create_new_single_table_tablespace(
space, path_or_name, is_path,
flags == DICT_TF_COMPACT ? 0 : flags,
@@ -325,7 +325,7 @@ dict_build_table_def_step(
mtr_commit(&mtr);
} else {
/* Create in the system tablespace: disallow new features */
- table->flags &= (~0 << DICT_TF_BITS) | DICT_TF_COMPACT;
+ table->flags &= (~0U << DICT_TF_BITS) | DICT_TF_COMPACT;
}
row = dict_create_sys_tables_tuple(table, node->heap);
diff --git a/storage/xtradb/dict/dict0load.c b/storage/xtradb/dict/dict0load.c
index 067c9d2b8f9..1d11868ef73 100644
--- a/storage/xtradb/dict/dict0load.c
+++ b/storage/xtradb/dict/dict0load.c
@@ -717,7 +717,7 @@ dict_sys_tables_get_flags(
return(ULINT_UNDEFINED);
}
- if (UNIV_UNLIKELY(flags & (~0 << DICT_TF_BITS))) {
+ if (UNIV_UNLIKELY(flags & (~0U << DICT_TF_BITS))) {
/* Some unused bits are set. */
return(ULINT_UNDEFINED);
}
@@ -1406,7 +1406,7 @@ err_len:
goto err_len;
}
type = mach_read_from_4(field);
- if (UNIV_UNLIKELY(type & (~0 << DICT_IT_BITS))) {
+ if (UNIV_UNLIKELY(type & (~0U << DICT_IT_BITS))) {
return("unknown SYS_INDEXES.TYPE bits");
}
@@ -1771,7 +1771,7 @@ err_len:
flags2 = mach_read_from_4(field);
- if (flags2 & (~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT))) {
+ if (flags2 & (~0U << (DICT_TF2_BITS - DICT_TF2_SHIFT))) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Warning: table ", stderr);
ut_print_filename(stderr, name);
@@ -1780,7 +1780,7 @@ err_len:
" has unknown flags %lx.\n",
(ulong) flags2);
- flags2 &= ~(~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT));
+ flags2 &= ~(~0U << (DICT_TF2_BITS - DICT_TF2_SHIFT));
}
flags |= flags2 << DICT_TF2_SHIFT;
@@ -1913,7 +1913,7 @@ err_exit:
if (!fil_open_single_table_tablespace(
TRUE, table->space,
table->flags == DICT_TF_COMPACT ? 0 :
- table->flags & ~(~0 << DICT_TF_BITS), name, NULL)) {
+ table->flags & ~(~0U << DICT_TF_BITS), name, NULL)) {
/* We failed to find a sensible
tablespace file */
diff --git a/storage/xtradb/dict/dict0mem.c b/storage/xtradb/dict/dict0mem.c
index 40099c06823..18917a30ff6 100644
--- a/storage/xtradb/dict/dict0mem.c
+++ b/storage/xtradb/dict/dict0mem.c
@@ -69,7 +69,7 @@ dict_mem_table_create(
DBUG_ENTER("dict_mem_table_create");
ut_ad(name);
- ut_a(!(flags & (~0 << DICT_TF2_BITS)));
+ ut_a(!(flags & (~0U << DICT_TF2_BITS)));
heap = mem_heap_create(DICT_HEAP_SIZE);
diff --git a/storage/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c
index 67ad5ef7855..e824526e097 100644
--- a/storage/xtradb/fil/fil0fil.c
+++ b/storage/xtradb/fil/fil0fil.c
@@ -3868,7 +3868,7 @@ skip_write:
}
if (space_id != id
- || space_flags != (flags & ~(~0 << DICT_TF_BITS))) {
+ || space_flags != (flags & ~(~0U << DICT_TF_BITS))) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: tablespace id and flags in file ",
diff --git a/storage/xtradb/fsp/fsp0fsp.c b/storage/xtradb/fsp/fsp0fsp.c
index 2d145f44bab..8927e7c5841 100644
--- a/storage/xtradb/fsp/fsp0fsp.c
+++ b/storage/xtradb/fsp/fsp0fsp.c
@@ -249,8 +249,7 @@ fsp_fill_free_list(
then we do not allocate more extents */
ulint space, /*!< in: space */
fsp_header_t* header, /*!< in/out: space header */
- mtr_t* mtr) /*!< in/out: mini-transaction */
- __attribute__((nonnull));
+ mtr_t* mtr); /*!< in/out: mini-transaction */
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
@@ -279,7 +278,7 @@ fseg_alloc_free_page_low(
in which the page should be initialized.
If init_mtr!=mtr, but the page is already
latched in mtr, do not initialize the page. */
- __attribute__((warn_unused_result, nonnull));
+ __attribute__((warn_unused_result));
#endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**
@@ -1572,7 +1571,7 @@ Allocates a single free page from a space. The page is marked as used.
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
(init_mtr == mtr, or the page was not previously freed in mtr)
@retval block (not allocated or initialized) otherwise */
-static __attribute__((nonnull, warn_unused_result))
+static __attribute__((warn_unused_result))
buf_block_t*
fsp_alloc_free_page(
/*================*/
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index cb4a8f2357a..0c6449ef183 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -7544,29 +7544,7 @@ i_s_innodb_changed_pages_fill(
while(log_online_bitmap_iterator_next(&i) &&
(!srv_max_changed_pages ||
- output_rows_num < srv_max_changed_pages) &&
- /*
- There is no need to compare both start LSN and end LSN fields
- with maximum value. It's enough to compare only start LSN.
- Example:
-
- max_lsn = 100
- \\\\\\\\\\\\\\\\\\\\\\\\\|\\\\\\\\ - Query 1
- I------I I-------I I-------------I I----I
- ////////////////// | - Query 2
- 1 2 3 4
-
- Query 1:
- SELECT * FROM INNODB_CHANGED_PAGES WHERE start_lsn < 100
- will select 1,2,3 bitmaps
- Query 2:
- SELECT * FROM INNODB_CHANGED_PAGES WHERE end_lsn < 100
- will select 1,2 bitmaps
-
- The condition start_lsn <= 100 will be false after reading
- 1,2,3 bitmaps which suits for both cases.
- */
- LOG_BITMAP_ITERATOR_START_LSN(i) <= max_lsn)
+ output_rows_num < srv_max_changed_pages))
{
if (!LOG_BITMAP_ITERATOR_PAGE_CHANGED(i))
continue;
diff --git a/storage/xtradb/include/btr0cur.h b/storage/xtradb/include/btr0cur.h
index 7b56c1bbb6e..7f6fd34635f 100644
--- a/storage/xtradb/include/btr0cur.h
+++ b/storage/xtradb/include/btr0cur.h
@@ -261,7 +261,7 @@ btr_cur_update_alloc_zip(
FALSE=update-in-place */
mtr_t* mtr, /*!< in: mini-transaction */
trx_t* trx) /*!< in: NULL or transaction */
- __attribute__((nonnull (1, 2, 3, 6), warn_unused_result));
+ __attribute__((warn_unused_result));
/*************************************************************//**
Updates a record when the update causes no size changes in its fields.
@return DB_SUCCESS or error number */
@@ -345,8 +345,7 @@ btr_cur_del_mark_set_clust_rec(
const ulint* offsets,/*!< in: rec_get_offsets(rec) */
ibool val, /*!< in: value to set */
que_thr_t* thr, /*!< in: query thread */
- mtr_t* mtr) /*!< in: mtr */
- __attribute__((nonnull));
+ mtr_t* mtr); /*!< in: mtr */
/***********************************************************//**
Sets a secondary index record delete mark to TRUE or FALSE.
@return DB_SUCCESS, DB_LOCK_WAIT, or error number */
@@ -499,8 +498,7 @@ btr_cur_disown_inherited_fields(
dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
const upd_t* update, /*!< in: update vector */
- mtr_t* mtr) /*!< in/out: mini-transaction */
- __attribute__((nonnull(2,3,4,5,6)));
+ mtr_t* mtr); /*!< in/out: mini-transaction */
/** Operation code for btr_store_big_rec_extern_fields(). */
enum blob_op {
@@ -545,7 +543,7 @@ btr_store_big_rec_extern_fields(
mtr_t* btr_mtr, /*!< in: mtr containing the
latches to the clustered index */
enum blob_op op) /*! in: operation code */
- __attribute__((nonnull, warn_unused_result));
+ __attribute__((warn_unused_result));
/*******************************************************************//**
Frees the space in an externally stored field to the file space
@@ -621,8 +619,7 @@ btr_push_update_extern_fields(
/*==========================*/
dtuple_t* tuple, /*!< in/out: data tuple */
const upd_t* update, /*!< in: update vector */
- mem_heap_t* heap) /*!< in: memory heap */
- __attribute__((nonnull));
+ mem_heap_t* heap); /*!< in: memory heap */
/***********************************************************//**
Sets a secondary index record's delete mark to the given value. This
function is only used by the insert buffer merge mechanism. */
diff --git a/storage/xtradb/include/btr0sea.h b/storage/xtradb/include/btr0sea.h
index 39c0a66fb9a..bdffe402277 100644
--- a/storage/xtradb/include/btr0sea.h
+++ b/storage/xtradb/include/btr0sea.h
@@ -205,14 +205,14 @@ hash_table_t*
btr_search_get_hash_table(
/*======================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((nonnull,pure,warn_unused_result));
+ __attribute__((warn_unused_result));
UNIV_INLINE
rw_lock_t*
btr_search_get_latch(
/*=================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((nonnull,pure,warn_unused_result));
+ __attribute__((warn_unused_result));
/*********************************************************************//**
Returns the AHI partition number corresponding to a given index ID. */
@@ -229,8 +229,7 @@ UNIV_INLINE
void
btr_search_index_init(
/*===============*/
- dict_index_t* index) /*!< in: index */
- __attribute__((nonnull));
+ dict_index_t* index); /*!< in: index */
UNIV_INLINE
void
diff --git a/storage/xtradb/include/buf0buddy.ic b/storage/xtradb/include/buf0buddy.ic
index d7053881caa..2b5e62e97b2 100644
--- a/storage/xtradb/include/buf0buddy.ic
+++ b/storage/xtradb/include/buf0buddy.ic
@@ -51,7 +51,7 @@ buf_buddy_alloc_low(
buf_pool->mutex was temporarily
released */
ibool have_page_hash_mutex)
- __attribute__((malloc, nonnull));
+ __attribute__((malloc));
/**********************************************************************//**
Deallocate a block. */
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index 23692c92c09..d584062a81f 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.h
@@ -274,8 +274,7 @@ buf_relocate(
buf_page_t* bpage, /*!< in/out: control block being relocated;
buf_page_get_state(bpage) must be
BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_ZIP_PAGE */
- buf_page_t* dpage) /*!< in/out: destination control block */
- __attribute__((nonnull));
+ buf_page_t* dpage); /*!< in/out: destination control block */
/*********************************************************************//**
Gets the current size of buffer buf_pool in bytes.
@return size in bytes */
diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h
index 121f9241cbc..5a3465fd9c5 100644
--- a/storage/xtradb/include/dict0dict.h
+++ b/storage/xtradb/include/dict0dict.h
@@ -605,7 +605,7 @@ ulint
dict_index_is_clust(
/*================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((nonnull, pure, warn_unused_result));
+ __attribute__((warn_unused_result));
/********************************************************************//**
Check whether the index is unique.
@return nonzero for unique index, zero for other indexes */
@@ -614,7 +614,7 @@ ulint
dict_index_is_unique(
/*=================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((nonnull, pure, warn_unused_result));
+ __attribute__((warn_unused_result));
/********************************************************************//**
Check whether the index is the insert buffer tree.
@return nonzero for insert buffer, zero for other indexes */
@@ -623,7 +623,7 @@ ulint
dict_index_is_ibuf(
/*===============*/
const dict_index_t* index) /*!< in: index */
- __attribute__((nonnull, pure, warn_unused_result));
+ __attribute__((warn_unused_result));
/********************************************************************//**
Check whether the index is a secondary index or the insert buffer tree.
@return nonzero for insert buffer, zero for other indexes */
@@ -632,7 +632,7 @@ ulint
dict_index_is_sec_or_ibuf(
/*======================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((nonnull, pure, warn_unused_result));
+ __attribute__((warn_unused_result));
/********************************************************************//**
Gets the number of user-defined columns in a table in the dictionary
@@ -643,7 +643,7 @@ ulint
dict_table_get_n_user_cols(
/*=======================*/
const dict_table_t* table) /*!< in: table */
- __attribute__((nonnull, pure, warn_unused_result));
+ __attribute__((warn_unused_result));
/********************************************************************//**
Gets the number of system columns in a table in the dictionary cache.
@return number of system (e.g., ROW_ID) columns of a table */
@@ -662,7 +662,7 @@ ulint
dict_table_get_n_cols(
/*==================*/
const dict_table_t* table) /*!< in: table */
- __attribute__((nonnull, pure, warn_unused_result));
+ __attribute__((warn_unused_result));
#ifdef UNIV_DEBUG
/********************************************************************//**
Gets the nth column of a table.
@@ -1313,7 +1313,7 @@ ulint
dict_index_is_corrupted(
/*====================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((nonnull, pure, warn_unused_result));
+ __attribute__((warn_unused_result));
#endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**
@@ -1324,7 +1324,7 @@ void
dict_set_corrupted(
/*===============*/
dict_index_t* index) /*!< in/out: index */
- UNIV_COLD __attribute__((nonnull));
+ UNIV_COLD;
/**********************************************************************//**
Flags an index corrupted in the data dictionary cache only. This
diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h
index ba98eed7701..2bdad46ae08 100644
--- a/storage/xtradb/include/dict0mem.h
+++ b/storage/xtradb/include/dict0mem.h
@@ -87,7 +87,7 @@ combination of types */
/* @{ */
#define DICT_TF_FORMAT_SHIFT 5 /* file format */
#define DICT_TF_FORMAT_MASK \
-((~(~0 << (DICT_TF_BITS - DICT_TF_FORMAT_SHIFT))) << DICT_TF_FORMAT_SHIFT)
+((~(~0U << (DICT_TF_BITS - DICT_TF_FORMAT_SHIFT))) << DICT_TF_FORMAT_SHIFT)
#define DICT_TF_FORMAT_51 0 /*!< InnoDB/MySQL up to 5.1 */
#define DICT_TF_FORMAT_ZIP 1 /*!< InnoDB plugin for 5.1:
compressed tables,
diff --git a/storage/xtradb/include/dyn0dyn.h b/storage/xtradb/include/dyn0dyn.h
index 62ed862e82c..e3517108a29 100644
--- a/storage/xtradb/include/dyn0dyn.h
+++ b/storage/xtradb/include/dyn0dyn.h
@@ -47,9 +47,8 @@ UNIV_INLINE
dyn_array_t*
dyn_array_create(
/*=============*/
- dyn_array_t* arr) /*!< in/out memory buffer of
+ dyn_array_t* arr); /*!< in/out memory buffer of
size sizeof(dyn_array_t) */
- __attribute__((nonnull));
/************************************************************//**
Frees a dynamic array. */
UNIV_INLINE
@@ -70,7 +69,7 @@ dyn_array_open(
dyn_array_t* arr, /*!< in: dynamic array */
ulint size) /*!< in: size in bytes of the buffer; MUST be
smaller than DYN_ARRAY_DATA_SIZE! */
- __attribute__((nonnull, warn_unused_result));
+ __attribute__((warn_unused_result));
/*********************************************************************//**
Closes the buffer returned by dyn_array_open. */
UNIV_INLINE
@@ -78,8 +77,7 @@ void
dyn_array_close(
/*============*/
dyn_array_t* arr, /*!< in: dynamic array */
- const byte* ptr) /*!< in: end of used space */
- __attribute__((nonnull));
+ const byte* ptr); /*!< in: end of used space */
/*********************************************************************//**
Makes room on top of a dyn array and returns a pointer to
the added element. The caller must copy the element to
@@ -91,7 +89,7 @@ dyn_array_push(
/*===========*/
dyn_array_t* arr, /*!< in/out: dynamic array */
ulint size) /*!< in: size in bytes of the element */
- __attribute__((nonnull, warn_unused_result));
+ __attribute__((warn_unused_result));
/************************************************************//**
Returns pointer to an element in dyn array.
@return pointer to element */
@@ -102,7 +100,7 @@ dyn_array_get_element(
const dyn_array_t* arr, /*!< in: dyn array */
ulint pos) /*!< in: position of element
in bytes from array start */
- __attribute__((nonnull, warn_unused_result));
+ __attribute__((warn_unused_result));
/************************************************************//**
Returns the size of stored data in a dyn array.
@return data size in bytes */
@@ -111,7 +109,7 @@ ulint
dyn_array_get_data_size(
/*====================*/
const dyn_array_t* arr) /*!< in: dyn array */
- __attribute__((nonnull, warn_unused_result, pure));
+ __attribute__((warn_unused_result));
/************************************************************//**
Gets the first block in a dyn array.
@param arr dyn array
@@ -145,7 +143,7 @@ ulint
dyn_block_get_used(
/*===============*/
const dyn_block_t* block) /*!< in: dyn array block */
- __attribute__((nonnull, warn_unused_result, pure));
+ __attribute__((warn_unused_result));
/********************************************************************//**
Gets pointer to the start of data in a dyn array block.
@return pointer to data */
@@ -154,7 +152,7 @@ byte*
dyn_block_get_data(
/*===============*/
const dyn_block_t* block) /*!< in: dyn array block */
- __attribute__((nonnull, warn_unused_result, pure));
+ __attribute__((warn_unused_result));
/********************************************************//**
Pushes n bytes to a dyn array. */
UNIV_INLINE
diff --git a/storage/xtradb/include/dyn0dyn.ic b/storage/xtradb/include/dyn0dyn.ic
index 177877ed1fd..239d0547c6c 100644
--- a/storage/xtradb/include/dyn0dyn.ic
+++ b/storage/xtradb/include/dyn0dyn.ic
@@ -36,7 +36,7 @@ dyn_block_t*
dyn_array_add_block(
/*================*/
dyn_array_t* arr) /*!< in/out: dyn array */
- __attribute__((nonnull, warn_unused_result));
+ __attribute__((warn_unused_result));
/********************************************************************//**
Gets the number of used bytes in a dyn array block.
diff --git a/storage/xtradb/include/fsp0fsp.h b/storage/xtradb/include/fsp0fsp.h
index f07e3decc66..0b813182947 100644
--- a/storage/xtradb/include/fsp0fsp.h
+++ b/storage/xtradb/include/fsp0fsp.h
@@ -42,7 +42,7 @@ Created 12/18/1995 Heikki Tuuri
#define FSP_FLAGS_POS_PAGE_SSIZE 6
/** Bit mask of the PAGE_SSIZE field */
#define FSP_FLAGS_MASK_PAGE_SSIZE \
- ((~(~0 << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \
+ ((~(~0U << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \
<< FSP_FLAGS_POS_PAGE_SSIZE)
/** Return the value of the PAGE_SSIZE field */
#define FSP_FLAGS_GET_PAGE_SSIZE(flags) \
diff --git a/storage/xtradb/include/log0online.h b/storage/xtradb/include/log0online.h
index 02d75001505..2462263dec2 100644
--- a/storage/xtradb/include/log0online.h
+++ b/storage/xtradb/include/log0online.h
@@ -37,19 +37,25 @@ log_online_bitmap_file_range_t;
/** An iterator over changed page info */
typedef struct log_bitmap_iterator_struct log_bitmap_iterator_t;
-/*********************************************************************//**
-Initializes the online log following subsytem. */
+/** Initialize the constant part of the log tracking subsystem */
+UNIV_INTERN
+void
+log_online_init(void);
+
+/** Initialize the dynamic part of the log tracking subsystem */
UNIV_INTERN
void
log_online_read_init(void);
-/*=======================*/
-/*********************************************************************//**
-Shuts down the online log following subsystem. */
+/** Shut down the dynamic part of the log tracking subsystem */
UNIV_INTERN
void
log_online_read_shutdown(void);
-/*===========================*/
+
+/** Shut down the constant part of the log tracking subsystem */
+UNIV_INTERN
+void
+log_online_shutdown(void);
/*********************************************************************//**
Reads and parses the redo log up to last checkpoint LSN to build the changed
@@ -159,6 +165,8 @@ struct log_online_bitmap_file_range_struct {
/** Struct for an iterator through all bits of changed pages bitmap blocks */
struct log_bitmap_iterator_struct
{
+ ib_uint64_t max_lsn; /*!< End LSN of the
+ range */
ibool failed; /*!< Has the iteration
stopped prematurely */
log_online_bitmap_file_range_t in_files; /*!< The bitmap files
diff --git a/storage/xtradb/include/mach0data.h b/storage/xtradb/include/mach0data.h
index 81c0866f367..d9a4a9170c7 100644
--- a/storage/xtradb/include/mach0data.h
+++ b/storage/xtradb/include/mach0data.h
@@ -51,7 +51,7 @@ ulint
mach_read_from_1(
/*=============*/
const byte* b) /*!< in: pointer to byte */
- __attribute__((nonnull, pure));
+ __attribute__((warn_unused_result));
/*******************************************************//**
The following function is used to store data in two consecutive
bytes. We store the most significant byte to the lower address. */
@@ -112,7 +112,7 @@ ulint
mach_read_from_3(
/*=============*/
const byte* b) /*!< in: pointer to 3 bytes */
- __attribute__((nonnull, pure));
+ __attribute__((warn_unused_result));
/*******************************************************//**
The following function is used to store data in four consecutive
bytes. We store the most significant byte to the lowest address. */
@@ -131,7 +131,7 @@ ulint
mach_read_from_4(
/*=============*/
const byte* b) /*!< in: pointer to four bytes */
- __attribute__((nonnull, pure));
+ __attribute__((warn_unused_result));
/*********************************************************//**
Writes a ulint in a compressed form (1..5 bytes).
@return stored size in bytes */
@@ -158,7 +158,7 @@ ulint
mach_read_compressed(
/*=================*/
const byte* b) /*!< in: pointer to memory from where to read */
- __attribute__((nonnull, pure));
+ __attribute__((warn_unused_result));
/*******************************************************//**
The following function is used to store data in 6 consecutive
bytes. We store the most significant byte to the lowest address. */
@@ -177,7 +177,7 @@ ib_uint64_t
mach_read_from_6(
/*=============*/
const byte* b) /*!< in: pointer to 6 bytes */
- __attribute__((nonnull, pure));
+ __attribute__((warn_unused_result));
/*******************************************************//**
The following function is used to store data in 7 consecutive
bytes. We store the most significant byte to the lowest address. */
@@ -196,7 +196,7 @@ ib_uint64_t
mach_read_from_7(
/*=============*/
const byte* b) /*!< in: pointer to 7 bytes */
- __attribute__((nonnull, pure));
+ __attribute__((warn_unused_result));
/*******************************************************//**
The following function is used to store data in 8 consecutive
bytes. We store the most significant byte to the lowest address. */
@@ -241,7 +241,7 @@ ib_uint64_t
mach_ull_read_compressed(
/*=====================*/
const byte* b) /*!< in: pointer to memory from where to read */
- __attribute__((nonnull, pure));
+ __attribute__((warn_unused_result));
/*********************************************************//**
Writes a 64-bit integer in a compressed form (1..11 bytes).
@return size in bytes */
@@ -268,7 +268,7 @@ ib_uint64_t
mach_ull_read_much_compressed(
/*==========================*/
const byte* b) /*!< in: pointer to memory from where to read */
- __attribute__((nonnull, pure));
+ __attribute__((warn_unused_result));
/*********************************************************//**
Reads a ulint in a compressed form if the log record fully contains it.
@return pointer to end of the stored field, NULL if not complete */
diff --git a/storage/xtradb/include/mtr0mtr.h b/storage/xtradb/include/mtr0mtr.h
index 031fccd300c..bb60ffbd9bb 100644
--- a/storage/xtradb/include/mtr0mtr.h
+++ b/storage/xtradb/include/mtr0mtr.h
@@ -205,8 +205,7 @@ UNIV_INTERN
void
mtr_commit(
/*=======*/
- mtr_t* mtr) /*!< in/out: mini-transaction */
- __attribute__((nonnull));
+ mtr_t* mtr); /*!< in/out: mini-transaction */
/**********************************************************//**
Sets and returns a savepoint in mtr.
@return savepoint */
@@ -311,7 +310,7 @@ mtr_memo_contains(
mtr_t* mtr, /*!< in: mtr */
const void* object, /*!< in: object to search */
ulint type) /*!< in: type of object */
- __attribute__((warn_unused_result, nonnull));
+ __attribute__((warn_unused_result));
/**********************************************************//**
Checks if memo contains the given page.
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index 71da5ea6125..618d6f540ae 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -515,9 +515,10 @@ os_file_create_simple_no_error_handling_func(
it would be enabled otherwise). */
ibool* success);/*!< out: TRUE if succeed, FALSE if error */
/****************************************************************//**
-Tries to disable OS caching on an opened file descriptor. */
+Tries to disable OS caching on an opened file descriptor.
+@return TRUE if operation is success and FALSE otherwise */
UNIV_INTERN
-void
+ibool
os_file_set_nocache(
/*================*/
int fd, /*!< in: file descriptor to alter */
diff --git a/storage/xtradb/include/page0page.h b/storage/xtradb/include/page0page.h
index b4755dce61d..6c8281b40cb 100644
--- a/storage/xtradb/include/page0page.h
+++ b/storage/xtradb/include/page0page.h
@@ -231,8 +231,7 @@ ulint
page_header_get_offs(
/*=================*/
const page_t* page, /*!< in: page */
- ulint field) /*!< in: PAGE_FREE, ... */
- __attribute__((nonnull, pure));
+ ulint field); /*!< in: PAGE_FREE, ... */
/*************************************************************//**
Returns the pointer stored in the given header field, or NULL. */
@@ -792,8 +791,7 @@ page_copy_rec_list_end(
buf_block_t* block, /*!< in: index page containing rec */
rec_t* rec, /*!< in: record on page */
dict_index_t* index, /*!< in: record descriptor */
- mtr_t* mtr) /*!< in: mtr */
- __attribute__((nonnull));
+ mtr_t* mtr); /*!< in: mtr */
/*************************************************************//**
Copies records from page to new_page, up to the given record, NOT
including that record. Infimum and supremum records are not copied.
@@ -808,8 +806,7 @@ page_copy_rec_list_start(
buf_block_t* block, /*!< in: index page containing rec */
rec_t* rec, /*!< in: record on page */
dict_index_t* index, /*!< in: record descriptor */
- mtr_t* mtr) /*!< in: mtr */
- __attribute__((nonnull));
+ mtr_t* mtr); /*!< in: mtr */
/*************************************************************//**
Deletes records from a page from a given record onward, including that record.
The infimum and supremum records are not deleted. */
@@ -852,8 +849,7 @@ page_move_rec_list_end(
buf_block_t* block, /*!< in: index page from where to move */
rec_t* split_rec, /*!< in: first record to move */
dict_index_t* index, /*!< in: record descriptor */
- mtr_t* mtr) /*!< in: mtr */
- __attribute__((nonnull(1, 2, 4, 5)));
+ mtr_t* mtr); /*!< in: mtr */
/*************************************************************//**
Moves record list start to another page. Moved records do not include
split_rec.
@@ -877,8 +873,7 @@ page_dir_split_slot(
page_t* page, /*!< in: index page */
page_zip_des_t* page_zip,/*!< in/out: compressed page whose
uncompressed part will be written, or NULL */
- ulint slot_no)/*!< in: the directory slot */
- __attribute__((nonnull(1)));
+ ulint slot_no);/*!< in: the directory slot */
/*************************************************************//**
Tries to balance the given directory slot with too few records
with the upper neighbor, so that there are at least the minimum number
@@ -890,8 +885,7 @@ page_dir_balance_slot(
/*==================*/
page_t* page, /*!< in/out: index page */
page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
- ulint slot_no)/*!< in: the directory slot */
- __attribute__((nonnull(1)));
+ ulint slot_no);/*!< in: the directory slot */
/**********************************************************//**
Parses a log record of a record list end or start deletion.
@return end of log record or NULL */
diff --git a/storage/xtradb/include/page0zip.h b/storage/xtradb/include/page0zip.h
index a33407e78bc..abd62ab99a5 100644
--- a/storage/xtradb/include/page0zip.h
+++ b/storage/xtradb/include/page0zip.h
@@ -402,8 +402,7 @@ page_zip_reorganize(
out: data, n_blobs,
m_start, m_end, m_nonempty */
dict_index_t* index, /*!< in: index of the B-tree node */
- mtr_t* mtr) /*!< in: mini-transaction */
- __attribute__((nonnull));
+ mtr_t* mtr); /*!< in: mini-transaction */
#ifndef UNIV_HOTBACKUP
/**********************************************************************//**
Copy the records of a page byte for byte. Do not copy the page header
@@ -436,7 +435,7 @@ page_zip_parse_compress(
byte* end_ptr,/*!< in: buffer end */
page_t* page, /*!< out: uncompressed page */
page_zip_des_t* page_zip)/*!< out: compressed page */
- __attribute__((nonnull(1,2)));
+ __attribute__((warn_unused_result));
/**********************************************************************//**
Calculate the compressed page checksum.
diff --git a/storage/xtradb/include/rem0rec.h b/storage/xtradb/include/rem0rec.h
index 9dd96f609ea..18e89eacccd 100644
--- a/storage/xtradb/include/rem0rec.h
+++ b/storage/xtradb/include/rem0rec.h
@@ -626,8 +626,7 @@ rec_copy(
/*=====*/
void* buf, /*!< in: buffer */
const rec_t* rec, /*!< in: physical record */
- const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
- __attribute__((nonnull));
+ const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
#ifndef UNIV_HOTBACKUP
/**********************************************************//**
Determines the size of a data tuple prefix in a temporary file.
diff --git a/storage/xtradb/include/row0upd.h b/storage/xtradb/include/row0upd.h
index 16c069d5ae8..e23a71374c2 100644
--- a/storage/xtradb/include/row0upd.h
+++ b/storage/xtradb/include/row0upd.h
@@ -232,9 +232,8 @@ row_upd_index_replace_new_col_vals_index_pos(
/*!< in: if TRUE, limit the replacement to
ordering fields of index; note that this
does not work for non-clustered indexes. */
- mem_heap_t* heap) /*!< in: memory heap for allocating and
+ mem_heap_t* heap); /*!< in: memory heap for allocating and
copying the new values */
- __attribute__((nonnull));
/***********************************************************//**
Replaces the new column values stored in the update vector to the index entry
given. */
@@ -295,7 +294,7 @@ row_upd_changes_ord_field_binary_func(
compile time */
const row_ext_t*ext) /*!< NULL, or prefixes of the externally
stored columns in the old row */
- __attribute__((nonnull(1,2), warn_unused_result));
+ __attribute__((warn_unused_result));
#ifdef UNIV_DEBUG
# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \
row_upd_changes_ord_field_binary_func(index,update,thr,row,ext)
diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h
index b223f7cb39c..17f26956e78 100644
--- a/storage/xtradb/include/trx0trx.h
+++ b/storage/xtradb/include/trx0trx.h
@@ -90,7 +90,7 @@ trx_t*
trx_create(
/*=======*/
sess_t* sess) /*!< in: session */
- __attribute__((nonnull));
+ __attribute__((warn_unused_result));
/********************************************************************//**
Creates a transaction object for MySQL.
@return own: transaction object */
@@ -119,7 +119,7 @@ void
trx_free_prepared(
/*==============*/
trx_t* trx) /*!< in, own: trx object */
- UNIV_COLD __attribute__((nonnull));
+ UNIV_COLD;
/********************************************************************//**
Frees a transaction object for MySQL. */
UNIV_INTERN
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index d198fbf021b..a7475bbf396 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -64,7 +64,7 @@ component, i.e. we show M.N.P as M.N */
(INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 38.5
+#define PERCONA_INNODB_VERSION 38.8
#endif
#define INNODB_VERSION_STR MYSQL_SERVER_VERSION
diff --git a/storage/xtradb/log/log0online.c b/storage/xtradb/log/log0online.c
index fa2c8b882bf..45739dffa5d 100644
--- a/storage/xtradb/log/log0online.c
+++ b/storage/xtradb/log/log0online.c
@@ -84,12 +84,14 @@ struct log_bitmap_struct {
both the correct type and the tree does
not mind its overwrite during
rbt_next() tree traversal. */
- mutex_t mutex; /*!< mutex protecting all the fields.*/
};
/* The log parsing and bitmap output struct instance */
static struct log_bitmap_struct* log_bmp_sys;
+/* Mutex protecting log_bmp_sys */
+static mutex_t log_bmp_sys_mutex;
+
/** File name stem for bitmap files. */
static const char* bmp_file_name_stem = "ib_modified_log_";
@@ -188,7 +190,7 @@ log_online_set_page_bit(
byte search_page[MODIFIED_PAGE_BLOCK_SIZE];
byte *page_ptr;
- ut_ad(mutex_own(&log_bmp_sys->mutex));
+ ut_ad(mutex_own(&log_bmp_sys_mutex));
ut_a(space != ULINT_UNDEFINED);
ut_a(page_no != ULINT_UNDEFINED);
@@ -339,7 +341,7 @@ log_online_read_last_tracked_lsn(void)
ib_uint64_t result;
ib_uint64_t read_offset = log_bmp_sys->out.offset;
- while (!checksum_ok && read_offset > 0 && !is_last_page)
+ while ((!checksum_ok || !is_last_page) && read_offset > 0)
{
read_offset -= MODIFIED_PAGE_BLOCK_SIZE;
log_bmp_sys->out.offset = read_offset;
@@ -609,12 +611,19 @@ log_online_is_bitmap_file(
&& (!strcmp(stem, bmp_file_name_stem)));
}
-/*********************************************************************//**
-Initialize the online log following subsytem. */
+/** Initialize the constant part of the log tracking subsystem */
+UNIV_INTERN
+void
+log_online_init(void)
+{
+ mutex_create(log_bmp_sys_mutex_key, &log_bmp_sys_mutex,
+ SYNC_LOG_ONLINE);
+}
+
+/** Initialize the dynamic part of the log tracking subsystem */
UNIV_INTERN
void
log_online_read_init(void)
-/*======================*/
{
ibool success;
ib_uint64_t tracking_start_lsn
@@ -635,9 +644,6 @@ log_online_read_init(void)
log_bmp_sys->read_buf = ut_align(log_bmp_sys->read_buf_ptr,
OS_FILE_LOG_BLOCK_SIZE);
- mutex_create(log_bmp_sys_mutex_key, &log_bmp_sys->mutex,
- SYNC_LOG_ONLINE);
-
/* Initialize bitmap file directory from srv_data_home and add a path
separator if needed. */
srv_data_home_len = strlen(srv_data_home);
@@ -720,6 +726,7 @@ log_online_read_init(void)
ulint size_high;
ib_uint64_t last_tracked_lsn;
ib_uint64_t file_start_lsn;
+ ibool need_rotate;
success = os_file_get_size(log_bmp_sys->out.file, &size_low,
&size_high);
@@ -742,7 +749,11 @@ log_online_read_init(void)
}
last_tracked_lsn = log_online_read_last_tracked_lsn();
+ /* Do not rotate if we truncated the file to zero length - we
+ can just start writing there */
+ need_rotate = (last_tracked_lsn != 0);
if (!last_tracked_lsn) {
+
last_tracked_lsn = last_file_start_lsn;
}
@@ -754,7 +765,10 @@ log_online_read_init(void)
} else {
file_start_lsn = tracking_start_lsn;
}
- if (!log_online_rotate_bitmap_file(file_start_lsn)) {
+
+ if (need_rotate
+ && !log_online_rotate_bitmap_file(file_start_lsn)) {
+
exit(1);
}
@@ -782,14 +796,18 @@ log_online_read_init(void)
log_set_tracked_lsn(tracking_start_lsn);
}
-/*********************************************************************//**
-Shut down the online log following subsystem. */
+/** Shut down the dynamic part of the log tracking subsystem */
UNIV_INTERN
void
log_online_read_shutdown(void)
-/*==========================*/
{
- ib_rbt_node_t *free_list_node = log_bmp_sys->page_free_list;
+ ib_rbt_node_t *free_list_node;
+
+ mutex_enter(&log_bmp_sys_mutex);
+
+ srv_track_changed_pages = FALSE;
+
+ free_list_node = log_bmp_sys->page_free_list;
if (log_bmp_sys->out.file != os_file_invalid) {
os_file_close(log_bmp_sys->out.file);
@@ -804,10 +822,21 @@ log_online_read_shutdown(void)
free_list_node = next;
}
- mutex_free(&log_bmp_sys->mutex);
-
ut_free(log_bmp_sys->read_buf_ptr);
ut_free(log_bmp_sys);
+ log_bmp_sys = NULL;
+
+ srv_redo_log_thread_started = FALSE;
+
+ mutex_exit(&log_bmp_sys_mutex);
+}
+
+/** Shut down the constant part of the log tracking subsystem */
+UNIV_INTERN
+void
+log_online_shutdown(void)
+{
+ mutex_free(&log_bmp_sys_mutex);
}
/*********************************************************************//**
@@ -858,7 +887,7 @@ log_online_parse_redo_log(void)
ulint len = 0;
- ut_ad(mutex_own(&log_bmp_sys->mutex));
+ ut_ad(mutex_own(&log_bmp_sys_mutex));
while (ptr != end
&& log_bmp_sys->next_parse_lsn < log_bmp_sys->end_lsn) {
@@ -950,7 +979,7 @@ log_online_add_to_parse_buf(
ulint actual_data_len = (end_offset >= start_offset)
? end_offset - start_offset : 0;
- ut_ad(mutex_own(&log_bmp_sys->mutex));
+ ut_ad(mutex_own(&log_bmp_sys_mutex));
ut_memcpy(log_bmp_sys->parse_buf_end, log_block + start_offset,
actual_data_len);
@@ -976,7 +1005,7 @@ log_online_parse_redo_log_block(
{
ulint block_data_len;
- ut_ad(mutex_own(&log_bmp_sys->mutex));
+ ut_ad(mutex_own(&log_bmp_sys_mutex));
block_data_len = log_block_get_data_len(log_block);
@@ -1004,7 +1033,7 @@ log_online_follow_log_seg(
byte* log_block_end = log_bmp_sys->read_buf
+ (block_end_lsn - block_start_lsn);
- ut_ad(mutex_own(&log_bmp_sys->mutex));
+ ut_ad(mutex_own(&log_bmp_sys_mutex));
mutex_enter(&log_sys->mutex);
log_group_read_log_seg(LOG_RECOVER, log_bmp_sys->read_buf,
@@ -1068,7 +1097,7 @@ log_online_follow_log_group(
ib_uint64_t block_start_lsn = contiguous_lsn;
ib_uint64_t block_end_lsn;
- ut_ad(mutex_own(&log_bmp_sys->mutex));
+ ut_ad(mutex_own(&log_bmp_sys_mutex));
log_bmp_sys->next_parse_lsn = log_bmp_sys->start_lsn;
log_bmp_sys->parse_buf_end = log_bmp_sys->parse_buf;
@@ -1108,10 +1137,35 @@ log_online_write_bitmap_page(
{
ibool success;
- ut_ad(mutex_own(&log_bmp_sys->mutex));
+ ut_ad(mutex_own(&log_bmp_sys_mutex));
/* Simulate a write error */
- DBUG_EXECUTE_IF("bitmap_page_write_error", return FALSE;);
+ DBUG_EXECUTE_IF("bitmap_page_write_error",
+ {
+ ulint space_id
+ = mach_read_from_4(block
+ + MODIFIED_PAGE_SPACE_ID);
+ if (space_id > 0) {
+ fprintf(stderr, "InnoDB: Error: "
+ "simulating bitmap write "
+ "error in "
+ "log_online_write_bitmap_page "
+ "for space ID %lu\n",
+ space_id);
+ return FALSE;
+ }
+ });
+
+ /* A crash injection site that ensures last checkpoint LSN > last
+ tracked LSN, so that LSN tracking for this interval is tested. */
+ DBUG_EXECUTE_IF("crash_before_bitmap_write",
+ {
+ ulint space_id
+ = mach_read_from_4(block
+ + MODIFIED_PAGE_SPACE_ID);
+ if (space_id > 0)
+ DBUG_SUICIDE();
+ });
success = os_file_write(log_bmp_sys->out.name, log_bmp_sys->out.file,
block,
@@ -1161,7 +1215,7 @@ log_online_write_bitmap(void)
const ib_rbt_node_t *last_bmp_tree_node;
ibool success = TRUE;
- ut_ad(mutex_own(&log_bmp_sys->mutex));
+ ut_ad(mutex_own(&log_bmp_sys_mutex));
if (log_bmp_sys->out.offset >= srv_max_bitmap_file_size) {
if (!log_online_rotate_bitmap_file(log_bmp_sys->start_lsn)) {
@@ -1204,7 +1258,11 @@ log_online_write_bitmap(void)
rbt_next(log_bmp_sys->modified_pages, bmp_tree_node);
DBUG_EXECUTE_IF("bitmap_page_2_write_error",
- DBUG_SET("+d,bitmap_page_write_error"););
+ if (bmp_tree_node)
+ {
+ DBUG_SET("+d,bitmap_page_write_error");
+ DBUG_SET("-d,bitmap_page_2_write_error");
+ });
}
rbt_reset(log_bmp_sys->modified_pages);
@@ -1225,11 +1283,16 @@ log_online_follow_redo_log(void)
log_group_t* group;
ibool result;
- mutex_enter(&log_bmp_sys->mutex);
+ if (!srv_track_changed_pages)
+ return TRUE;
+
+ DEBUG_SYNC_C("log_online_follow_redo_log");
+
+ mutex_enter(&log_bmp_sys_mutex);
if (!srv_track_changed_pages) {
- mutex_exit(&log_bmp_sys->mutex);
- return FALSE;
+ mutex_exit(&log_bmp_sys_mutex);
+ return TRUE;
}
/* Grab the LSN of the last checkpoint, we will parse up to it */
@@ -1238,7 +1301,7 @@ log_online_follow_redo_log(void)
mutex_exit(&(log_sys->mutex));
if (log_bmp_sys->end_lsn == log_bmp_sys->start_lsn) {
- mutex_exit(&log_bmp_sys->mutex);
+ mutex_exit(&log_bmp_sys_mutex);
return TRUE;
}
@@ -1253,15 +1316,11 @@ log_online_follow_redo_log(void)
group = UT_LIST_GET_NEXT(log_groups, group);
}
- /* A crash injection site that ensures last checkpoint LSN > last
- tracked LSN, so that LSN tracking for this interval is tested. */
- DBUG_EXECUTE_IF("crash_before_bitmap_write", DBUG_SUICIDE(););
-
result = log_online_write_bitmap();
log_bmp_sys->start_lsn = log_bmp_sys->end_lsn;
log_set_tracked_lsn(log_bmp_sys->start_lsn);
- mutex_exit(&log_bmp_sys->mutex);
+ mutex_exit(&log_bmp_sys_mutex);
return result;
}
@@ -1608,6 +1667,8 @@ log_online_bitmap_iterator_init(
{
ut_a(i);
+ i->max_lsn = max_lsn;
+
if (UNIV_UNLIKELY(min_lsn > max_lsn)) {
/* Empty range */
@@ -1716,6 +1777,9 @@ log_online_bitmap_iterator_next(
return TRUE;
}
+ if (i->end_lsn >= i->max_lsn && i->last_page_in_run)
+ return FALSE;
+
while (!checksum_ok)
{
while (i->in.size < MODIFIED_PAGE_BLOCK_SIZE
@@ -1808,6 +1872,7 @@ log_online_purge_changed_page_bitmaps(
log_online_bitmap_file_range_t bitmap_files;
size_t i;
ibool result = FALSE;
+ ibool log_bmp_sys_inited = FALSE;
if (lsn == 0) {
lsn = IB_ULONGLONG_MAX;
@@ -1816,13 +1881,18 @@ log_online_purge_changed_page_bitmaps(
if (srv_redo_log_thread_started) {
/* User requests might happen with both enabled and disabled
tracking */
- mutex_enter(&log_bmp_sys->mutex);
+ log_bmp_sys_inited = TRUE;
+ mutex_enter(&log_bmp_sys_mutex);
+ if (!srv_redo_log_thread_started) {
+ log_bmp_sys_inited = FALSE;
+ mutex_exit(&log_bmp_sys_mutex);
+ }
}
if (!log_online_setup_bitmap_file_range(&bitmap_files, 0,
IB_ULONGLONG_MAX)) {
- if (srv_redo_log_thread_started) {
- mutex_exit(&log_bmp_sys->mutex);
+ if (log_bmp_sys_inited) {
+ mutex_exit(&log_bmp_sys_mutex);
}
return TRUE;
}
@@ -1858,7 +1928,7 @@ log_online_purge_changed_page_bitmaps(
}
}
- if (srv_redo_log_thread_started) {
+ if (log_bmp_sys_inited) {
if (lsn > log_bmp_sys->end_lsn) {
ib_uint64_t new_file_lsn;
if (lsn == IB_ULONGLONG_MAX) {
@@ -1874,7 +1944,7 @@ log_online_purge_changed_page_bitmaps(
}
}
- mutex_exit(&log_bmp_sys->mutex);
+ mutex_exit(&log_bmp_sys_mutex);
}
free(bitmap_files.files);
diff --git a/storage/xtradb/mach/mach0data.c b/storage/xtradb/mach/mach0data.c
index 00378f036c9..9669516244d 100644
--- a/storage/xtradb/mach/mach0data.c
+++ b/storage/xtradb/mach/mach0data.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -55,7 +55,6 @@ mach_parse_compressed(
if (flag < 0x80UL) {
*val = flag;
return(ptr + 1);
-
}
/* Workaround GCC bug
@@ -64,7 +63,11 @@ mach_parse_compressed(
function, causing and out-of-bounds read if we are reading a short
integer close to the end of buffer. */
#if defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__clang__)
- asm volatile("": : :"memory");
+#define DEPLOY_FENCE
+#endif
+
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
#endif
if (flag < 0xC0UL) {
@@ -75,8 +78,13 @@ mach_parse_compressed(
*val = mach_read_from_2(ptr) & 0x7FFFUL;
return(ptr + 2);
+ }
- } else if (flag < 0xE0UL) {
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+#endif
+
+ if (flag < 0xE0UL) {
if (end_ptr < ptr + 3) {
return(NULL);
}
@@ -84,7 +92,13 @@ mach_parse_compressed(
*val = mach_read_from_3(ptr) & 0x3FFFFFUL;
return(ptr + 3);
- } else if (flag < 0xF0UL) {
+ }
+
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+#endif
+
+ if (flag < 0xF0UL) {
if (end_ptr < ptr + 4) {
return(NULL);
}
@@ -92,14 +106,20 @@ mach_parse_compressed(
*val = mach_read_from_4(ptr) & 0x1FFFFFFFUL;
return(ptr + 4);
- } else {
- ut_ad(flag == 0xF0UL);
-
- if (end_ptr < ptr + 5) {
- return(NULL);
- }
-
- *val = mach_read_from_4(ptr + 1);
- return(ptr + 5);
}
+
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+#endif
+
+#undef DEPLOY_FENCE
+
+ ut_ad(flag == 0xF0UL);
+
+ if (end_ptr < ptr + 5) {
+ return(NULL);
+ }
+
+ *val = mach_read_from_4(ptr + 1);
+ return(ptr + 5);
}
diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c
index 21f8c3eed11..25692e73db1 100644
--- a/storage/xtradb/os/os0file.c
+++ b/storage/xtradb/os/os0file.c
@@ -961,50 +961,15 @@ next_file:
char* full_path;
int ret;
struct stat statinfo;
-#ifdef HAVE_READDIR_R
- char dirent_buf[sizeof(struct dirent)
- + _POSIX_PATH_MAX + 100];
- /* In /mysys/my_lib.c, _POSIX_PATH_MAX + 1 is used as
- the max file name len; but in most standards, the
- length is NAME_MAX; we add 100 to be even safer */
-#endif
next_file:
-#ifdef HAVE_READDIR_R
- ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
-
- if (ret != 0
-#ifdef UNIV_AIX
- /* On AIX, only if we got non-NULL 'ent' (result) value and
- a non-zero 'ret' (return) value, it indicates a failed
- readdir_r() call. An NULL 'ent' with an non-zero 'ret'
- would indicate the "end of the directory" is reached. */
- && ent != NULL
-#endif
- ) {
- fprintf(stderr,
- "InnoDB: cannot read directory %s, error %lu\n",
- dirname, (ulong)ret);
-
- return(-1);
- }
-
- if (ent == NULL) {
- /* End of directory */
-
- return(1);
- }
-
- ut_a(strlen(ent->d_name) < _POSIX_PATH_MAX + 100 - 1);
-#else
ent = readdir(dir);
if (ent == NULL) {
return(1);
}
-#endif
ut_a(strlen(ent->d_name) < OS_FILE_MAX_PATH);
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
@@ -1382,9 +1347,10 @@ os_file_create_simple_no_error_handling_func(
}
/****************************************************************//**
-Tries to disable OS caching on an opened file descriptor. */
+Tries to disable OS caching on an opened file descriptor.
+@return TRUE if operation is success and FALSE otherwise */
UNIV_INTERN
-void
+ibool
os_file_set_nocache(
/*================*/
int fd /*!< in: file descriptor to alter */
@@ -1405,6 +1371,7 @@ os_file_set_nocache(
" InnoDB: Failed to set DIRECTIO_ON "
"on file %s: %s: %s, continuing anyway\n",
file_name, operation_name, strerror(errno_save));
+ return FALSE;
}
#elif defined(O_DIRECT)
if (fcntl(fd, F_SETFL, O_DIRECT) == -1) {
@@ -1422,8 +1389,10 @@ os_file_set_nocache(
"'Invalid argument' on Linux on tmpfs, "
"see MySQL Bug#26662\n");
}
+ return FALSE;
}
#endif
+ return TRUE;
}
/****************************************************************//**
@@ -1699,7 +1668,11 @@ try_again:
/* ALL_O_DIRECT: O_DIRECT also for transaction log file */
if (srv_unix_file_flush_method == SRV_UNIX_ALL_O_DIRECT) {
- os_file_set_nocache(file, name, mode_str);
+ /* Do fsync() on log files when setting O_DIRECT fails.
+ See log_io_complete() */
+ if (!os_file_set_nocache(file, name, mode_str)) {
+ srv_unix_file_flush_method = SRV_UNIX_O_DIRECT;
+ }
}
#ifdef USE_FILE_LOCK
diff --git a/storage/xtradb/rem/rem0rec.c b/storage/xtradb/rem/rem0rec.c
index d938aa696dd..5d55fa1add0 100644
--- a/storage/xtradb/rem/rem0rec.c
+++ b/storage/xtradb/rem/rem0rec.c
@@ -774,7 +774,7 @@ rec_get_nth_field_offs_old(
/**********************************************************//**
Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT.
@return total size */
-UNIV_INLINE __attribute__((warn_unused_result, nonnull(1,2)))
+UNIV_INLINE __attribute__((warn_unused_result))
ulint
rec_get_converted_size_comp_prefix_low(
/*===================================*/
diff --git a/storage/xtradb/row/row0merge.c b/storage/xtradb/row/row0merge.c
index 746eb8be261..580eca1efee 100644
--- a/storage/xtradb/row/row0merge.c
+++ b/storage/xtradb/row/row0merge.c
@@ -802,7 +802,7 @@ row_merge_write(
/********************************************************************//**
Read a merge record.
@return pointer to next record, or NULL on I/O error or end of list */
-static __attribute__((nonnull))
+static __attribute__((warn_unused_result))
const byte*
row_merge_read_rec(
/*===============*/
@@ -1168,7 +1168,7 @@ row_merge_cmp(
Reads clustered index of the table and create temporary files
containing the index entries for the indexes to be built.
@return DB_SUCCESS or error */
-static __attribute__((nonnull))
+static __attribute__((warn_unused_result))
ulint
row_merge_read_clustered_index(
/*===========================*/
diff --git a/storage/xtradb/row/row0purge.c b/storage/xtradb/row/row0purge.c
index 9018582f5d6..0187199f4f5 100644
--- a/storage/xtradb/row/row0purge.c
+++ b/storage/xtradb/row/row0purge.c
@@ -742,7 +742,7 @@ err_exit:
Fetches an undo log record and does the purge for the recorded operation.
If none left, or the current purge completed, returns the control to the
parent node, which is always a query thread node. */
-static __attribute__((nonnull))
+static
void
row_purge(
/*======*/
diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c
index 0acce91f2c4..3770a8804dd 100644
--- a/storage/xtradb/srv/srv0srv.c
+++ b/storage/xtradb/srv/srv0srv.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -3208,10 +3208,8 @@ srv_redo_log_follow_thread(
} while (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE);
- srv_track_changed_pages = FALSE;
log_online_read_shutdown();
os_event_set(srv_redo_log_thread_finished_event);
- srv_redo_log_thread_started = FALSE; /* Defensive, not required */
my_thread_end();
os_thread_exit(NULL);
@@ -3390,6 +3388,7 @@ srv_master_thread(
ib_uint64_t oldest_lsn;
ib_time_t last_print_time;
+ my_thread_init();
#ifdef UNIV_DEBUG_THREAD_CREATION
fprintf(stderr, "Master thread starts, id %lu\n",
os_thread_pf(os_thread_get_curr_id()));
@@ -4093,6 +4092,7 @@ suspend_thread:
os_event_wait(slot->event);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ my_thread_end();
os_thread_exit(NULL);
}
@@ -4117,6 +4117,7 @@ srv_purge_thread(
ulint n_total_purged = ULINT_UNDEFINED;
ulint next_itr_time;
+ my_thread_init();
ut_a(srv_n_purge_threads == 1);
#ifdef UNIV_PFS_THREAD
@@ -4222,6 +4223,8 @@ srv_purge_thread(
os_thread_pf(os_thread_get_curr_id()));
#endif /* UNIV_DEBUG_THREAD_CREATION */
+ my_thread_end();
+
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
os_thread_exit(NULL);
diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c
index 2d39cddbcce..ade62aa2797 100644
--- a/storage/xtradb/srv/srv0start.c
+++ b/storage/xtradb/srv/srv0start.c
@@ -1619,6 +1619,7 @@ innobase_start_or_create_for_mysql(void)
fsp_init();
log_init();
+ log_online_init();
lock_sys_create(srv_lock_table_size);
@@ -2465,6 +2466,7 @@ innobase_shutdown_for_mysql(void)
btr_search_disable();
ibuf_close();
+ log_online_shutdown();
log_shutdown();
trx_sys_file_format_close();
trx_sys_close();
diff --git a/storage/xtradb/trx/trx0roll.c b/storage/xtradb/trx/trx0roll.c
index 25c1d5d4692..96a679a243d 100644
--- a/storage/xtradb/trx/trx0roll.c
+++ b/storage/xtradb/trx/trx0roll.c
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 2017, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -610,12 +611,15 @@ trx_rollback_or_clean_all_recovered(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
+
#ifdef UNIV_PFS_THREAD
pfs_register_thread(trx_rollback_clean_thread_key);
#endif /* UNIV_PFS_THREAD */
trx_rollback_or_clean_recovered(TRUE);
+ my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
From 76f7aac8e06ed5d53669e764e643af0f5101e2b1 Mon Sep 17 00:00:00 2001
From: Sachin Setiya
Date: Wed, 19 Jul 2017 15:28:13 +0530
Subject: [PATCH 064/101] MDEV-13065 rpl.rpl_mdev-11092 fails sporadically in
buildbot
Problem
rpl.rpl_mdev-11092 fails in buildbot because after starting slave in
wait_for_slave_sql_error_and_skip.inc slave is started but there may be
chances that we have not skipped the last error and Last_SQL_Errno is
still not zero untill the end of rpl_end.inc , which will compare
Last_SQL_Errno to 0. So in this this case rpl_mdev-11092 fails.
Solution
After starting slave in wait_for_slave_sql_error_and_skip.inc we will wait for
Last_SQL_Errno to become 0.
---
mysql-test/include/wait_for_slave_sql_error_and_skip.inc | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/mysql-test/include/wait_for_slave_sql_error_and_skip.inc b/mysql-test/include/wait_for_slave_sql_error_and_skip.inc
index 9246c1839af..d68faaf04e7 100644
--- a/mysql-test/include/wait_for_slave_sql_error_and_skip.inc
+++ b/mysql-test/include/wait_for_slave_sql_error_and_skip.inc
@@ -66,6 +66,13 @@ if (!$slave_skip_counter) {
}
source include/start_slave.inc;
+# start_slave.inc returns when Slave_SQL_Running=Yes. But the slave
+# thread sets it before clearing Last_SQL_Errno. So we have to wait
+# for Last_SQL_Errno=0 separately.
+
+let $slave_param= Last_SQL_Errno;
+let $slave_param_value= 0;
+source include/wait_for_slave_param.inc;
--let $include_filename= wait_for_slave_sql_error_and_skip.inc [errno=$slave_sql_errno]
--source include/end_include_file.inc
From c8a0244e957bc4beff453f09c881bb51752d682c Mon Sep 17 00:00:00 2001
From: Daniel Bartholomew
Date: Wed, 19 Jul 2017 11:47:59 -0400
Subject: [PATCH 065/101] bump the VERSION
---
VERSION | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/VERSION b/VERSION
index 68358acf754..2905c37cc09 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
MYSQL_VERSION_MAJOR=5
MYSQL_VERSION_MINOR=5
-MYSQL_VERSION_PATCH=57
+MYSQL_VERSION_PATCH=58
MYSQL_VERSION_EXTRA=
From da2a838628796453c6ab93d51eca9e5aae45791d Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Wed, 19 Jul 2017 19:46:07 +0200
Subject: [PATCH 066/101] MDEV-12824 GCC 7 warning: this statement may fall
through [-Wimplicit-fallthrough=]
---
sql-common/client.c | 1 +
sql/item_func.cc | 5 +++--
sql/log.cc | 2 +-
sql/sql_repl.cc | 1 +
storage/federated/ha_federated.cc | 2 ++
storage/federatedx/ha_federatedx.cc | 2 ++
storage/heap/hp_extra.c | 1 +
storage/maria/ma_key_recover.c | 1 +
8 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/sql-common/client.c b/sql-common/client.c
index 6c1627ecb71..ca9929be77e 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1148,6 +1148,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
break;
case OPT_pipe:
options->protocol = MYSQL_PROTOCOL_PIPE;
+ break;
case OPT_connect_timeout:
case OPT_timeout:
if (opt_arg)
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 13ea5291edc..0ca8f700bfc 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -848,8 +848,9 @@ void Item_func_num1::fix_length_and_dec()
{
DBUG_ENTER("Item_func_num1::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
- switch (cached_result_type= args[0]->cast_to_int_type()) {
+ switch (args[0]->cast_to_int_type()) {
case INT_RESULT:
+ cached_result_type= INT_RESULT;
max_length= args[0]->max_length;
unsigned_flag= args[0]->unsigned_flag;
break;
@@ -860,8 +861,8 @@ void Item_func_num1::fix_length_and_dec()
max_length= float_length(decimals);
break;
case TIME_RESULT:
- cached_result_type= DECIMAL_RESULT;
case DECIMAL_RESULT:
+ cached_result_type= DECIMAL_RESULT;
decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC
max_length= args[0]->max_length;
break;
diff --git a/sql/log.cc b/sql/log.cc
index 3cad1716ca4..ee92f22adb8 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -9405,8 +9405,8 @@ int TC_LOG_BINLOG::recover(LOG_INFO *linfo, const char *last_log_name,
sizeof(xev->xid));
if (!x || my_hash_insert(&xids, x))
goto err2;
- break;
}
+ break;
}
case BINLOG_CHECKPOINT_EVENT:
if (first_round && do_xa)
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index ebe89e2b4a0..0ddeeaa0266 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -2665,6 +2665,7 @@ impossible position";
loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK);
break;
}
+ /* fall through */
default:
errmsg = "could not find next log";
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 927921d6df4..401e1b35bb1 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -1423,6 +1423,7 @@ bool ha_federated::create_where_from_key(String *to,
}
break;
}
+ /* fall through */
case HA_READ_KEY_OR_NEXT:
DBUG_PRINT("info", ("federated HA_READ_KEY_OR_NEXT %d", i));
if (emit_key_part_name(&tmp, key_part) ||
@@ -1442,6 +1443,7 @@ bool ha_federated::create_where_from_key(String *to,
goto err;
break;
}
+ /* fall through */
case HA_READ_KEY_OR_PREV:
DBUG_PRINT("info", ("federated HA_READ_KEY_OR_PREV %d", i));
if (emit_key_part_name(&tmp, key_part) ||
diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc
index aae26758c78..0a24fe9c910 100644
--- a/storage/federatedx/ha_federatedx.cc
+++ b/storage/federatedx/ha_federatedx.cc
@@ -1342,6 +1342,7 @@ bool ha_federatedx::create_where_from_key(String *to,
}
break;
}
+ /* fall through */
case HA_READ_KEY_OR_NEXT:
DBUG_PRINT("info", ("federatedx HA_READ_KEY_OR_NEXT %d", i));
if (emit_key_part_name(&tmp, key_part) ||
@@ -1361,6 +1362,7 @@ bool ha_federatedx::create_where_from_key(String *to,
goto err;
break;
}
+ /* fall through */
case HA_READ_KEY_OR_PREV:
DBUG_PRINT("info", ("federatedx HA_READ_KEY_OR_PREV %d", i));
if (emit_key_part_name(&tmp, key_part) ||
diff --git a/storage/heap/hp_extra.c b/storage/heap/hp_extra.c
index c83efd5af61..9a19f818d3b 100644
--- a/storage/heap/hp_extra.c
+++ b/storage/heap/hp_extra.c
@@ -34,6 +34,7 @@ int heap_extra(register HP_INFO *info, enum ha_extra_function function)
switch (function) {
case HA_EXTRA_RESET_STATE:
heap_reset(info);
+ /* fall through */
case HA_EXTRA_NO_READCHECK:
info->opt_flag&= ~READ_CHECK_USED; /* No readcheck */
break;
diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c
index ae9427981ea..3f91f233cb6 100644
--- a/storage/maria/ma_key_recover.c
+++ b/storage/maria/ma_key_recover.c
@@ -1169,6 +1169,7 @@ uint _ma_apply_redo_index(MARIA_HA *info,
goto err;
}
page_length= page.size;
+ break;
}
case KEY_OP_NONE:
default:
From dc8b2fb03a5a2dff4687eb8dad042b34730b5210 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Wed, 19 Jul 2017 19:47:38 +0200
Subject: [PATCH 067/101] MDEV-11896 thd_get_error_context_description race
condition
Change the semantics of thd_get_error_context_description().
It no longer expects the caller to lock LOCK_thread_count
(no caller ever did that anyway), but takes care of it internally.
---
include/service_versions.h | 2 +-
sql/sql_class.cc | 10 ++++------
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/include/service_versions.h b/include/service_versions.h
index cca190b811c..ce4a0c931f7 100644
--- a/include/service_versions.h
+++ b/include/service_versions.h
@@ -31,4 +31,4 @@
#define VERSION_my_sha1 0x0100
#define VERSION_logger 0x0100
#define VERSION_thd_autoinc 0x0100
-#define VERSION_thd_error_context 0x0100
+#define VERSION_thd_error_context 0x0200
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index bebdd82ea83..da1a0e43ac1 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -725,12 +725,6 @@ extern "C"
@param buffer pointer to preferred result buffer
@param length length of buffer
@param max_query_len how many chars of query to copy (0 for all)
-
- @req LOCK_thread_count
-
- @note LOCK_thread_count mutex is not necessary when the function is invoked on
- the currently running thread (current_thd) or if the caller in some other
- way guarantees that access to thd->query is serialized.
@return Pointer to string
*/
@@ -744,6 +738,9 @@ char *thd_get_error_context_description(THD *thd, char *buffer,
const Security_context *sctx= &thd->main_security_ctx;
char header[256];
int len;
+
+ mysql_mutex_lock(&LOCK_thread_count);
+
/*
The pointers thd->query and thd->proc_info might change since they are
being modified concurrently. This is acceptable for proc_info since its
@@ -799,6 +796,7 @@ char *thd_get_error_context_description(THD *thd, char *buffer,
}
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
+ mysql_mutex_unlock(&LOCK_thread_count);
if (str.c_ptr_safe() == buffer)
return buffer;
From 2fcd8c12522f5f935066b661c42b5b7cb416d148 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Wed, 19 Jul 2017 22:22:14 +0200
Subject: [PATCH 068/101] MDEV-13173 An RLIKE that previously worked on 10.0
now returns "Got error 'pcre_exec: recursion limit of 100 exceeded' from
regexp"
1. use Regexp_processor_pcre::set_recursion_limit() to set the
recursion limit depending on the current available stack size
2. make pcre stack frame to be estimated no less than 500 bytes.
sometimes pcre estimates it too low, even though the manual
says 500+16 bytes (it was estimated only 188 for me, actual
frame size was 512).
3. do it for embedded too
---
mysql-test/r/func_regexp_pcre.result | 32 ++++++++++++++++++++++++++++
mysql-test/t/func_regexp_pcre.test | 19 +++++++++++++++++
sql/item_cmpfunc.cc | 15 ++++++++++++-
sql/item_cmpfunc.h | 2 ++
sql/item_strfunc.cc | 14 ++++++++++++
sql/item_strfunc.h | 2 ++
sql/mysqld.cc | 10 ++++-----
7 files changed, 87 insertions(+), 7 deletions(-)
diff --git a/mysql-test/r/func_regexp_pcre.result b/mysql-test/r/func_regexp_pcre.result
index af7230d2ad0..7d1a0915b6f 100644
--- a/mysql-test/r/func_regexp_pcre.result
+++ b/mysql-test/r/func_regexp_pcre.result
@@ -879,3 +879,35 @@ SELECT 1 FROM dual WHERE ('Alpha,Bravo,Charlie,Delta,Echo,Foxtrot,StrataCentral,
1
Warnings:
Warning 1139 Got error 'pcre_exec: recursion limit of NUM exceeded' from regexp
+SELECT CONCAT(REPEAT('100,',500),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$';
+CONCAT(REPEAT('100,',500),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$'
+1
+SELECT CONCAT(REPEAT('100,',600),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$';
+CONCAT(REPEAT('100,',600),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$'
+0
+Warnings:
+Warning 1139 Got error 'pcre_exec: recursion limit of NUM exceeded' from regexp
+SELECT REGEXP_INSTR(CONCAT(REPEAT('100,',500),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$');
+REGEXP_INSTR(CONCAT(REPEAT('100,',500),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$')
+1
+SELECT REGEXP_INSTR(CONCAT(REPEAT('100,',600),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$');
+REGEXP_INSTR(CONCAT(REPEAT('100,',600),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$')
+0
+Warnings:
+Warning 1139 Got error 'pcre_exec: recursion limit of NUM exceeded' from regexp
+SELECT LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'));
+LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'))
+671
+SELECT LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'));
+LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'))
+0
+Warnings:
+Warning 1139 Got error 'pcre_exec: recursion limit of NUM exceeded' from regexp
+SELECT LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''));
+LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''))
+0
+SELECT LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''));
+LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''))
+803
+Warnings:
+Warning 1139 Got error 'pcre_exec: recursion limit of NUM exceeded' from regexp
diff --git a/mysql-test/t/func_regexp_pcre.test b/mysql-test/t/func_regexp_pcre.test
index 8e3adad0037..f2f7781dd08 100644
--- a/mysql-test/t/func_regexp_pcre.test
+++ b/mysql-test/t/func_regexp_pcre.test
@@ -430,3 +430,22 @@ SELECT CAST(0xE001 AS BINARY) REGEXP @regCheck;
--echo # MDEV-12420: Testing recursion overflow
--replace_regex /[0-9]+ exceeded/NUM exceeded/
SELECT 1 FROM dual WHERE ('Alpha,Bravo,Charlie,Delta,Echo,Foxtrot,StrataCentral,Golf,Hotel,India,Juliet,Kilo,Lima,Mike,StrataL3,November,Oscar,StrataL2,Sand,P3,P4SwitchTest,Arsys,Poppa,ExtensionMgr,Arp,Quebec,Romeo,StrataApiV2,PtReyes,Sierra,SandAcl,Arrow,Artools,BridgeTest,Tango,SandT,PAlaska,Namespace,Agent,Qos,PatchPanel,ProjectReport,Ark,Gimp,Agent,SliceAgent,Arnet,Bgp,Ale,Tommy,Central,AsicPktTestLib,Hsc,SandL3,Abuild,Pca9555,Standby,ControllerDut,CalSys,SandLib,Sb820,PointV2,BfnLib,Evpn,BfnSdk,Sflow,ManagementActive,AutoTest,GatedTest,Bgp,Sand,xinetd,BfnAgentLib,bf-utils,Hello,BfnState,Eos,Artest,Qos,Scd,ThermoMgr,Uniform,EosUtils,Eb,FanController,Central,BfnL3,BfnL2,tcp_wrappers,Victor,Environment,Route,Failover,Whiskey,Xray,Gimp,BfnFixed,Strata,SoCal,XApi,Msrp,XpProfile,tcpdump,PatchPanel,ArosTest,FhTest,Arbus,XpAcl,MacConc,XpApi,telnet,QosTest,Alpha2,BfnVlan,Stp,VxlanControllerTest,MplsAgent,Bravo2,Lanz,BfnMbb,Intf,XCtrl,Unicast,SandTunnel,L3Unicast,Ipsec,MplsTest,Rsvp,EthIntf,StageMgr,Sol,MplsUtils,Nat,Ira,P4NamespaceDut,Counters,Charlie2,Aqlc,Mlag,Power,OpenFlow,Lag,RestApi,BfdTest,strongs,Sfa,CEosUtils,Adt746,MaintenanceMode,MlagDut,EosImage,IpEth,MultiProtocol,Launcher,Max3179,Snmp,Acl,IpEthTest,PhyEee,bf-syslibs,tacc,XpL2,p4-ar-switch,p4-bf-switch,LdpTest,BfnPhy,Mirroring,Phy6,Ptp' REGEXP '^((?!\b(Strata|StrataApi|StrataApiV2)\b).)*$');
+
+#
+# MDEV-13173 An RLIKE that previously worked on 10.0 now returns "Got error 'pcre_exec: recursion limit of 100 exceeded' from regexp"
+#
+SELECT CONCAT(REPEAT('100,',500),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$';
+--replace_regex /[0-9]+ exceeded/NUM exceeded/
+SELECT CONCAT(REPEAT('100,',600),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$';
+
+SELECT REGEXP_INSTR(CONCAT(REPEAT('100,',500),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$');
+--replace_regex /[0-9]+ exceeded/NUM exceeded/
+SELECT REGEXP_INSTR(CONCAT(REPEAT('100,',600),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$');
+
+SELECT LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'));
+--replace_regex /[0-9]+ exceeded/NUM exceeded/
+SELECT LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'));
+
+SELECT LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''));
+--replace_regex /[0-9]+ exceeded/NUM exceeded/
+SELECT LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''));
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 038a0ebabc2..0134f628c80 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -5110,7 +5110,7 @@ void Regexp_processor_pcre::set_recursion_limit(THD *thd)
DBUG_ASSERT(thd == current_thd);
stack_used= available_stack_size(thd->thread_stack, &stack_used);
m_pcre_extra.match_limit_recursion=
- (my_thread_stack_size - stack_used)/my_pcre_frame_size;
+ (my_thread_stack_size - STACK_MIN_SIZE - stack_used)/my_pcre_frame_size;
}
@@ -5372,6 +5372,12 @@ void Regexp_processor_pcre::fix_owner(Item_func *owner,
}
+bool Item_func_regex::fix_fields(THD *thd, Item **ref)
+{
+ re.set_recursion_limit(thd);
+ return Item_bool_func::fix_fields(thd, ref);
+}
+
void
Item_func_regex::fix_length_and_dec()
{
@@ -5398,6 +5404,13 @@ longlong Item_func_regex::val_int()
}
+bool Item_func_regexp_instr::fix_fields(THD *thd, Item **ref)
+{
+ re.set_recursion_limit(thd);
+ return Item_int_func::fix_fields(thd, ref);
+}
+
+
void
Item_func_regexp_instr::fix_length_and_dec()
{
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 17ad1bd8c7d..ba0af32d76f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1652,6 +1652,7 @@ public:
DBUG_VOID_RETURN;
}
longlong val_int();
+ bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp"; }
@@ -1679,6 +1680,7 @@ public:
DBUG_VOID_RETURN;
}
longlong val_int();
+ bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp_instr"; }
};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 22e13bf6c38..c3043adac47 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1343,6 +1343,13 @@ void Item_func_replace::fix_length_and_dec()
/*********************************************************************/
+bool Item_func_regexp_replace::fix_fields(THD *thd, Item **ref)
+{
+ re.set_recursion_limit(thd);
+ return Item_str_func::fix_fields(thd, ref);
+}
+
+
void Item_func_regexp_replace::fix_length_and_dec()
{
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 3))
@@ -1478,6 +1485,13 @@ err:
}
+bool Item_func_regexp_substr::fix_fields(THD *thd, Item **ref)
+{
+ re.set_recursion_limit(thd);
+ return Item_str_func::fix_fields(thd, ref);
+}
+
+
void Item_func_regexp_substr::fix_length_and_dec()
{
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 2))
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 769bde67cb1..1b133d1d885 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -231,6 +231,7 @@ public:
DBUG_VOID_RETURN;
}
String *val_str(String *str);
+ bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp_replace"; }
};
@@ -251,6 +252,7 @@ public:
DBUG_VOID_RETURN;
}
String *val_str(String *str);
+ bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp_substr"; }
};
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 32cdda9debc..d9320fa3bcf 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -3451,7 +3451,6 @@ sizeof(load_default_groups)/sizeof(load_default_groups[0]);
#endif
-#ifndef EMBEDDED_LIBRARY
/**
This function is used to check for stack overrun for pathological
cases of regular expressions and 'like' expressions.
@@ -3480,8 +3479,6 @@ check_enough_stack_size(int recurse_level)
return 0;
return check_enough_stack_size_slow();
}
-#endif
-
/*
@@ -3503,11 +3500,12 @@ static void init_pcre()
{
pcre_malloc= pcre_stack_malloc= my_str_malloc_mysqld;
pcre_free= pcre_stack_free= my_str_free_mysqld;
-#ifndef EMBEDDED_LIBRARY
pcre_stack_guard= check_enough_stack_size_slow;
/* See http://pcre.org/original/doc/html/pcrestack.html */
- my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0) + 16;
-#endif
+ my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0);
+ // pcre can underestimate its stack usage. Use a safe value, as in the manual
+ set_if_bigger(my_pcre_frame_size, 500);
+ my_pcre_frame_size += 16; // Again, safety margin, see the manual
}
From 7e507f262a826c9c799355755541120be8c7352a Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Thu, 20 Jul 2017 15:08:24 +0200
Subject: [PATCH 069/101] MDEV-13274 mysql_upgrade fails if
dbname+tablename+partioname > 64 chars
InnoDB fix will come in MDEV-13360.
Here I just fix upgrades from old unfixed InnoDBs - bad data
makes the following copying ALTER TABLE to fail.
---
mysql-test/r/mysql_upgrade.result | 23 ++++++++++++++++++++++-
mysql-test/t/mysql_upgrade.test | 25 ++++++++++++++++++++++++-
scripts/mysql_system_tables_fix.sql | 9 +++++++++
3 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result
index 9ba5344fad0..565423be624 100644
--- a/mysql-test/r/mysql_upgrade.result
+++ b/mysql-test/r/mysql_upgrade.result
@@ -464,4 +464,25 @@ even_longer_user_name_number_3_to_test_the_grantor_and_definer_field_length@loca
even_longer_user_name_number_3_to_test_the_grantor_and_definer_field_length@localhost
DROP USER very_long_user_name_number_1, very_long_user_name_number_2, even_longer_user_name_number_3_to_test_the_grantor_and_definer_field_length@localhost;
DROP PROCEDURE test.pr;
-End of tests
+use test;
+alter table mysql.innodb_table_stats modify last_update int not null;
+create table extralongname_extralongname_extralongname_extralongname_ext (
+id int(10) unsigned not null,
+created_date date not null,
+created timestamp not null,
+primary key (created,id,created_date)
+) engine=innodb stats_persistent=1 default charset=latin1
+partition by range (year(created_date))
+subpartition by hash (month(created_date))
+subpartitions 2 (
+partition p2007 values less than (2008),
+partition p2008 values less than (2009)
+);
+select length(table_name) from mysql.innodb_table_stats;
+length(table_name)
+79
+79
+79
+79
+drop table extralongname_extralongname_extralongname_extralongname_ext;
+End of 10.0 tests
diff --git a/mysql-test/t/mysql_upgrade.test b/mysql-test/t/mysql_upgrade.test
index 2ef469ba7c5..f8026df8770 100644
--- a/mysql-test/t/mysql_upgrade.test
+++ b/mysql-test/t/mysql_upgrade.test
@@ -1,6 +1,7 @@
-- source include/mysql_upgrade_preparation.inc
-- source include/have_working_dns.inc
-- source include/have_innodb.inc
+-- source include/have_partition.inc
#
# Basic test that we can run mysql_upgrde and that it finds the
@@ -166,4 +167,26 @@ SELECT grantor FROM mysql.tables_priv WHERE db = 'mysql' AND table_name = 'user'
DROP USER very_long_user_name_number_1, very_long_user_name_number_2, even_longer_user_name_number_3_to_test_the_grantor_and_definer_field_length@localhost;
DROP PROCEDURE test.pr;
---echo End of tests
+#
+# MDEV-13274 mysql_upgrade fails if dbname+tablename+partioname > 64 chars
+#
+use test;
+alter table mysql.innodb_table_stats modify last_update int not null;
+
+create table extralongname_extralongname_extralongname_extralongname_ext (
+ id int(10) unsigned not null,
+ created_date date not null,
+ created timestamp not null,
+ primary key (created,id,created_date)
+) engine=innodb stats_persistent=1 default charset=latin1
+ partition by range (year(created_date))
+ subpartition by hash (month(created_date))
+ subpartitions 2 (
+ partition p2007 values less than (2008),
+ partition p2008 values less than (2009)
+ );
+--exec $MYSQL_UPGRADE --skip-verbose --force 2>&1
+select length(table_name) from mysql.innodb_table_stats;
+drop table extralongname_extralongname_extralongname_extralongname_ext;
+
+--echo End of 10.0 tests
diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql
index f034af4f898..1bb601ef5f9 100644
--- a/scripts/mysql_system_tables_fix.sql
+++ b/scripts/mysql_system_tables_fix.sql
@@ -667,6 +667,15 @@ DROP PROCEDURE mysql.count_duplicate_host_names;
# Convering the host name to lower case for existing users
UPDATE user SET host=LOWER( host ) WHERE LOWER( host ) <> host;
+# fix bad data when upgrading from unfixed InnoDB (MDEV-13360)
+set @str="delete from innodb_index_stats where length(table_name) > 64";
+set @str=if(@have_innodb <> 0, @str, "set @dummy = 0");
+prepare stmt from @str;
+execute stmt;
+set @str=replace(@str, "innodb_index_stats", "innodb_table_stats");
+prepare stmt from @str;
+execute stmt;
+
# update timestamp fields in the innodb stat tables
set @str="alter table mysql.innodb_index_stats modify last_update timestamp not null default current_timestamp on update current_timestamp";
set @str=if(@have_innodb <> 0, @str, "set @dummy = 0");
From 3ef5596505bd8d80fa80d1cf7514550434eb1d79 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Thu, 20 Jul 2017 15:52:06 +0200
Subject: [PATCH 070/101] MDEV-13175 Adding a new enum value at the end of a
list triggers a table rebuild
Backport of 7e29f2d64fb from 10.1.
Create_field does not set BINARY_FLAG, so the check didn't work at all.
Also, character sets were already compared, so this check would've been
redundant (if it would've worked).
---
mysql-test/r/alter_table_online.result | 111 ++++++++++++++
mysql-test/r/gis-alter_table_online.result | 51 +++++++
mysql-test/t/alter_table_online.test | 165 +++++++++++++++++++++
mysql-test/t/gis-alter_table_online.test | 82 ++++++++++
sql/field.cc | 21 ++-
sql/field.h | 10 +-
6 files changed, 423 insertions(+), 17 deletions(-)
create mode 100644 mysql-test/r/gis-alter_table_online.result
create mode 100644 mysql-test/t/gis-alter_table_online.test
diff --git a/mysql-test/r/alter_table_online.result b/mysql-test/r/alter_table_online.result
index f416c53f42c..d1fc4a3bd93 100644
--- a/mysql-test/r/alter_table_online.result
+++ b/mysql-test/r/alter_table_online.result
@@ -73,3 +73,114 @@ drop table t1;
create table t1 (a int) partition by hash(a) partitions 2;
alter online table t1 modify a int comment 'test';
drop table t1;
+#
+# MDEV-8948 ALTER ... INPLACE does work for BINARY, BLOB
+#
+CREATE TABLE t1 (a BINARY(10));
+ALTER TABLE t1 MODIFY a BINARY(10), ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a VARBINARY(10));
+ALTER TABLE t1 MODIFY a VARBINARY(10), ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a TINYBLOB);
+ALTER TABLE t1 MODIFY a TINYBLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a MEDIUMBLOB);
+ALTER TABLE t1 MODIFY a MEDIUMBLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a BLOB);
+ALTER TABLE t1 MODIFY a BLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a LONGBLOB);
+ALTER TABLE t1 MODIFY a LONGBLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a CHAR(10));
+ALTER TABLE t1 MODIFY a CHAR(10), ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(10));
+ALTER TABLE t1 MODIFY a VARCHAR(10), ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a TINYTEXT);
+ALTER TABLE t1 MODIFY a TINYTEXT, ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a MEDIUMTEXT);
+ALTER TABLE t1 MODIFY a MEDIUMTEXT, ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a TEXT);
+ALTER TABLE t1 MODIFY a TEXT, ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a LONGTEXT);
+ALTER TABLE t1 MODIFY a LONGTEXT, ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a CHAR(10));
+ALTER TABLE t1 MODIFY a CHAR(10) COLLATE latin1_bin, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(10));
+ALTER TABLE t1 MODIFY a VARCHAR(10) COLLATE latin1_bin, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a TINYTEXT);
+ALTER TABLE t1 MODIFY a TINYTEXT COLLATE latin1_bin, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a MEDIUMTEXT);
+ALTER TABLE t1 MODIFY a MEDIUMTEXT COLLATE latin1_bin, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a TEXT);
+ALTER TABLE t1 MODIFY a TEXT COLLATE latin1_bin, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a LONGTEXT);
+ALTER TABLE t1 MODIFY a LONGTEXT COLLATE latin1_bin, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a CHAR(10) COLLATE latin1_bin);
+ALTER TABLE t1 MODIFY a CHAR(10) COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(10) COLLATE latin1_bin);
+ALTER TABLE t1 MODIFY a VARCHAR(10) COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a TINYTEXT COLLATE latin1_bin);
+ALTER TABLE t1 MODIFY a TINYTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a MEDIUMTEXT COLLATE latin1_bin);
+ALTER TABLE t1 MODIFY a MEDIUMTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a TEXT COLLATE latin1_bin);
+ALTER TABLE t1 MODIFY a TEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a LONGTEXT COLLATE latin1_bin);
+ALTER TABLE t1 MODIFY a LONGTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a CHAR(10) COLLATE latin1_general_ci);
+ALTER TABLE t1 MODIFY a CHAR(10) COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(10) COLLATE latin1_general_ci);
+ALTER TABLE t1 MODIFY a VARCHAR(10) COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a TINYTEXT COLLATE latin1_general_ci);
+ALTER TABLE t1 MODIFY a TINYTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a MEDIUMTEXT COLLATE latin1_general_ci);
+ALTER TABLE t1 MODIFY a MEDIUMTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a TEXT COLLATE latin1_general_ci);
+ALTER TABLE t1 MODIFY a TEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a LONGTEXT COLLATE latin1_general_ci);
+ALTER TABLE t1 MODIFY a LONGTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
diff --git a/mysql-test/r/gis-alter_table_online.result b/mysql-test/r/gis-alter_table_online.result
new file mode 100644
index 00000000000..ea7ab3b66bd
--- /dev/null
+++ b/mysql-test/r/gis-alter_table_online.result
@@ -0,0 +1,51 @@
+#
+# Start of 10.1 tests
+#
+#
+# MDEV-8948 ALTER ... INPLACE does work for BINARY, BLOB
+#
+CREATE TABLE t1 (a TINYBLOB);
+ALTER TABLE t1 MODIFY a GEOMETRY, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a MEDIUMBLOB);
+ALTER TABLE t1 MODIFY a GEOMETRY, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a BLOB);
+ALTER TABLE t1 MODIFY a GEOMETRY, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a LONGBLOB);
+ALTER TABLE t1 MODIFY a GEOMETRY, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a GEOMETRY);
+ALTER TABLE t1 MODIFY a TINYBLOB, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a GEOMETRY);
+ALTER TABLE t1 MODIFY a MEDIUMBLOB, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a GEOMETRY);
+ALTER TABLE t1 MODIFY a BLOB, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a GEOMETRY);
+ALTER TABLE t1 MODIFY a LONGBLOB, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a GEOMETRY);
+ALTER TABLE t1 MODIFY a POLYGON, ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
+DROP TABLE t1;
+CREATE TABLE t1 (a POLYGON);
+ALTER TABLE t1 MODIFY a GEOMETRY, ALGORITHM=INPLACE;
+DROP TABLE t1;
+CREATE TABLE t1 (a POLYGON);
+ALTER TABLE t1 MODIFY a POLYGON, ALGORITHM=INPLACE;
+DROP TABLE t1;
+#
+# End of 10.1 tests
+#
diff --git a/mysql-test/t/alter_table_online.test b/mysql-test/t/alter_table_online.test
index d9c2a2c4d4f..9062ecba35a 100644
--- a/mysql-test/t/alter_table_online.test
+++ b/mysql-test/t/alter_table_online.test
@@ -121,3 +121,168 @@ drop table t1;
create table t1 (a int) partition by hash(a) partitions 2;
alter online table t1 modify a int comment 'test';
drop table t1;
+
+--echo #
+--echo # MDEV-8948 ALTER ... INPLACE does work for BINARY, BLOB
+--echo #
+#
+# ALTER to the same [VAR]BINARY type
+#
+CREATE TABLE t1 (a BINARY(10));
+ALTER TABLE t1 MODIFY a BINARY(10), ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARBINARY(10));
+ALTER TABLE t1 MODIFY a VARBINARY(10), ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+#
+# ALTER to the same BLOB variant
+#
+CREATE TABLE t1 (a TINYBLOB);
+ALTER TABLE t1 MODIFY a TINYBLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a MEDIUMBLOB);
+ALTER TABLE t1 MODIFY a MEDIUMBLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BLOB);
+ALTER TABLE t1 MODIFY a BLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a LONGBLOB);
+ALTER TABLE t1 MODIFY a LONGBLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+#
+# ALTER to the same [VAR]CHAR type
+#
+CREATE TABLE t1 (a CHAR(10));
+ALTER TABLE t1 MODIFY a CHAR(10), ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARCHAR(10));
+ALTER TABLE t1 MODIFY a VARCHAR(10), ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+
+#
+# ALTER to the same TEXT variant
+#
+CREATE TABLE t1 (a TINYTEXT);
+ALTER TABLE t1 MODIFY a TINYTEXT, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a MEDIUMTEXT);
+ALTER TABLE t1 MODIFY a MEDIUMTEXT, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TEXT);
+ALTER TABLE t1 MODIFY a TEXT, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a LONGTEXT);
+ALTER TABLE t1 MODIFY a LONGTEXT, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+#
+# ALTER from a non-binary to a binary collation
+#
+CREATE TABLE t1 (a CHAR(10));
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a CHAR(10) COLLATE latin1_bin, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARCHAR(10));
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a VARCHAR(10) COLLATE latin1_bin, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TINYTEXT);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a TINYTEXT COLLATE latin1_bin, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a MEDIUMTEXT);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a MEDIUMTEXT COLLATE latin1_bin, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TEXT);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a TEXT COLLATE latin1_bin, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a LONGTEXT);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a LONGTEXT COLLATE latin1_bin, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+#
+# ALTER from a binary to a non-binary collation
+#
+CREATE TABLE t1 (a CHAR(10) COLLATE latin1_bin);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a CHAR(10) COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARCHAR(10) COLLATE latin1_bin);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a VARCHAR(10) COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TINYTEXT COLLATE latin1_bin);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a TINYTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a MEDIUMTEXT COLLATE latin1_bin);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a MEDIUMTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TEXT COLLATE latin1_bin);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a TEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a LONGTEXT COLLATE latin1_bin);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a LONGTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+#
+# ALTER from a non-binary collation to another non-binary collation
+#
+CREATE TABLE t1 (a CHAR(10) COLLATE latin1_general_ci);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a CHAR(10) COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARCHAR(10) COLLATE latin1_general_ci);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a VARCHAR(10) COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TINYTEXT COLLATE latin1_general_ci);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a TINYTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a MEDIUMTEXT COLLATE latin1_general_ci);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a MEDIUMTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TEXT COLLATE latin1_general_ci);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a TEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a LONGTEXT COLLATE latin1_general_ci);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a LONGTEXT COLLATE latin1_swedish_ci, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+# End of 10.0 tests
diff --git a/mysql-test/t/gis-alter_table_online.test b/mysql-test/t/gis-alter_table_online.test
new file mode 100644
index 00000000000..be6d2137e77
--- /dev/null
+++ b/mysql-test/t/gis-alter_table_online.test
@@ -0,0 +1,82 @@
+--source include/have_innodb.inc
+--source include/have_geometry.inc
+
+--echo #
+--echo # Start of 10.1 tests
+--echo #
+
+--echo #
+--echo # MDEV-8948 ALTER ... INPLACE does work for BINARY, BLOB
+--echo #
+
+#
+# Blob variants to GEOMETRY
+#
+CREATE TABLE t1 (a TINYBLOB);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a GEOMETRY, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a MEDIUMBLOB);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a GEOMETRY, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BLOB);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a GEOMETRY, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a LONGBLOB);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a GEOMETRY, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+#
+# GEOMETRY to BLOB variants
+#
+
+CREATE TABLE t1 (a GEOMETRY);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a TINYBLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a GEOMETRY);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a MEDIUMBLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a GEOMETRY);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a BLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a GEOMETRY);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a LONGBLOB, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+#
+# Different GEOMETRY types
+#
+
+# Can't do INPLACE from a supertype to a subtype
+CREATE TABLE t1 (a GEOMETRY);
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY a POLYGON, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+# Ok to do INPLACE from a subtype to a supertype
+CREATE TABLE t1 (a POLYGON);
+ALTER TABLE t1 MODIFY a GEOMETRY, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+# Ok to do INPLACE for two equal geometry subtypes
+CREATE TABLE t1 (a POLYGON);
+ALTER TABLE t1 MODIFY a POLYGON, ALGORITHM=INPLACE;
+DROP TABLE t1;
+
+
+--echo #
+--echo # End of 10.1 tests
+--echo #
diff --git a/sql/field.cc b/sql/field.cc
index 7d7fad2d84d..7a44bcadd3c 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -6403,9 +6403,6 @@ uint Field::is_equal(Create_field *new_field)
uint Field_str::is_equal(Create_field *new_field)
{
- if (field_flags_are_binary() != new_field->field_flags_are_binary())
- return 0;
-
return ((new_field->sql_type == real_type()) &&
new_field->charset == field_charset &&
new_field->length == max_display_length());
@@ -7810,9 +7807,6 @@ uint Field_blob::max_packed_col_length(uint max_length)
uint Field_blob::is_equal(Create_field *new_field)
{
- if (field_flags_are_binary() != new_field->field_flags_are_binary())
- return 0;
-
return ((new_field->sql_type == get_blob_type_from_length(max_data_length()))
&& new_field->charset == field_charset &&
new_field->pack_length == pack_length());
@@ -7933,6 +7927,18 @@ Field::geometry_type Field_geom::geometry_type_merge(geometry_type a,
return Field::GEOM_GEOMETRY;
}
+
+uint Field_geom::is_equal(Create_field *new_field)
+{
+ return new_field->sql_type == MYSQL_TYPE_GEOMETRY &&
+ /*
+ - Allow ALTER..INPLACE to supertype (GEOMETRY),
+ e.g. POINT to GEOMETRY or POLYGON to GEOMETRY.
+ - Allow ALTER..INPLACE to the same geometry type: POINT -> POINT
+ */
+ (new_field->geom_type == geom_type ||
+ new_field->geom_type == GEOM_GEOMETRY);
+}
#endif /*HAVE_SPATIAL*/
/****************************************************************************
@@ -8336,8 +8342,7 @@ uint Field_enum::is_equal(Create_field *new_field)
The fields are compatible if they have the same flags,
type, charset and have the same underlying length.
*/
- if (new_field->field_flags_are_binary() != field_flags_are_binary() ||
- new_field->sql_type != real_type() ||
+ if (new_field->sql_type != real_type() ||
new_field->charset != field_charset ||
new_field->pack_length != pack_length())
return IS_EQUAL_NO;
diff --git a/sql/field.h b/sql/field.h
index 2770b8be213..e7bd5532ae6 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1080,10 +1080,6 @@ protected:
const uchar *unpack_int64(uchar* to, const uchar *from, const uchar *from_end)
{ return unpack_int(to, from, from_end, 8); }
- bool field_flags_are_binary()
- {
- return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0;
- }
double pos_in_interval_val_real(Field *min, Field *max);
double pos_in_interval_val_str(Field *min, Field *max, uint data_offset);
};
@@ -2620,6 +2616,7 @@ public:
enum_field_types type() const { return MYSQL_TYPE_GEOMETRY; }
bool match_collation_to_optimize_range() const { return false; }
void sql_type(String &str) const;
+ uint is_equal(Create_field *new_field);
int store(const char *to, uint length, CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr, bool unsigned_val);
@@ -2967,11 +2964,6 @@ public:
uint uint_geom_type, Virtual_column_info *vcol_info,
engine_option_value *option_list, bool check_exists);
- bool field_flags_are_binary()
- {
- return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0;
- }
-
ha_storage_media field_storage_type() const
{
return (ha_storage_media)
From 0ec147b6174a8069c303a6d0bd4e3822fe16e4c2 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Thu, 20 Jul 2017 22:26:08 +0200
Subject: [PATCH 071/101] fix main.func_regexp_pcre on jessie-ppc64le
apparently it uses a smaller per-thread stack
---
mysql-test/r/func_regexp_pcre.result | 18 +++++++++---------
mysql-test/t/func_regexp_pcre.test | 8 ++++----
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/mysql-test/r/func_regexp_pcre.result b/mysql-test/r/func_regexp_pcre.result
index 7d1a0915b6f..4089966a7d7 100644
--- a/mysql-test/r/func_regexp_pcre.result
+++ b/mysql-test/r/func_regexp_pcre.result
@@ -879,32 +879,32 @@ SELECT 1 FROM dual WHERE ('Alpha,Bravo,Charlie,Delta,Echo,Foxtrot,StrataCentral,
1
Warnings:
Warning 1139 Got error 'pcre_exec: recursion limit of NUM exceeded' from regexp
-SELECT CONCAT(REPEAT('100,',500),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$';
-CONCAT(REPEAT('100,',500),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$'
+SELECT CONCAT(REPEAT('100,',400),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$';
+CONCAT(REPEAT('100,',400),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$'
1
SELECT CONCAT(REPEAT('100,',600),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$';
CONCAT(REPEAT('100,',600),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$'
0
Warnings:
Warning 1139 Got error 'pcre_exec: recursion limit of NUM exceeded' from regexp
-SELECT REGEXP_INSTR(CONCAT(REPEAT('100,',500),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$');
-REGEXP_INSTR(CONCAT(REPEAT('100,',500),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$')
+SELECT REGEXP_INSTR(CONCAT(REPEAT('100,',400),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$');
+REGEXP_INSTR(CONCAT(REPEAT('100,',400),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$')
1
SELECT REGEXP_INSTR(CONCAT(REPEAT('100,',600),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$');
REGEXP_INSTR(CONCAT(REPEAT('100,',600),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$')
0
Warnings:
Warning 1139 Got error 'pcre_exec: recursion limit of NUM exceeded' from regexp
-SELECT LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'));
-LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'))
-671
+SELECT LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',400/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'));
+LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',400/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'))
+535
SELECT LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'));
LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'))
0
Warnings:
Warning 1139 Got error 'pcre_exec: recursion limit of NUM exceeded' from regexp
-SELECT LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''));
-LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''))
+SELECT LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',400/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''));
+LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',400/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''))
0
SELECT LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''));
LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''))
diff --git a/mysql-test/t/func_regexp_pcre.test b/mysql-test/t/func_regexp_pcre.test
index f2f7781dd08..07de4b33271 100644
--- a/mysql-test/t/func_regexp_pcre.test
+++ b/mysql-test/t/func_regexp_pcre.test
@@ -434,18 +434,18 @@ SELECT 1 FROM dual WHERE ('Alpha,Bravo,Charlie,Delta,Echo,Foxtrot,StrataCentral,
#
# MDEV-13173 An RLIKE that previously worked on 10.0 now returns "Got error 'pcre_exec: recursion limit of 100 exceeded' from regexp"
#
-SELECT CONCAT(REPEAT('100,',500),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$';
+SELECT CONCAT(REPEAT('100,',400),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$';
--replace_regex /[0-9]+ exceeded/NUM exceeded/
SELECT CONCAT(REPEAT('100,',600),'101') RLIKE '^(([1-9][0-9]*),)*[1-9][0-9]*$';
-SELECT REGEXP_INSTR(CONCAT(REPEAT('100,',500),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$');
+SELECT REGEXP_INSTR(CONCAT(REPEAT('100,',400),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$');
--replace_regex /[0-9]+ exceeded/NUM exceeded/
SELECT REGEXP_INSTR(CONCAT(REPEAT('100,',600),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$');
-SELECT LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'));
+SELECT LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',400/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'));
--replace_regex /[0-9]+ exceeded/NUM exceeded/
SELECT LENGTH(REGEXP_SUBSTR(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$'));
-SELECT LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',500/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''));
+SELECT LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',400/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''));
--replace_regex /[0-9]+ exceeded/NUM exceeded/
SELECT LENGTH(REGEXP_REPLACE(CONCAT(REPEAT('100,',600/3),'101'), '^(([1-9][0-9]*),)*[1-9][0-9]*$', ''));
From 92cbe388b6839bc1e21abb9859c54c58fc1769cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?=
Date: Fri, 21 Jul 2017 16:05:20 +0300
Subject: [PATCH 072/101] MDEV-13325: InnoDB assert dict_sys->size > 0 during
ALTER TABLE
Problem was that dict_sys->size tries to maintain used memory
occupied by the data dictionary table and index objects.
However at least on table objects table->heap size can increase
between when table object is inserted to dict_sys and when
it is removed from dict_sys causing inconsistency on amount
of memory added to and removed from dict_sys->size variable.
Removed unnecessary dict_sys:size variable as it is really
used only for status output.
Introduced dict_sys_get_size function to calculate memory
occupied by the data dictionary table and index objects
that is then used on show engine innodb output.
dict_table_add_to_cache(),
dict_table_rename_in_cache(),
dict_table_remove_from_cache_low(),
dict_index_remove_from_cache_low(),
Remove size calculation.
srv_printf_innodb_monitor(): Use dict_sys_get_size function to
get dictionary memory allocated.
xtradb_internal_hash_tables_fill_table(): Use dict_sys_get_size
function to get dictionary memory allocated.
---
storage/innobase/dict/dict0dict.cc | 57 +++++++++++++++++-----------
storage/innobase/include/dict0dict.h | 10 +++--
storage/innobase/srv/srv0srv.cc | 2 +-
storage/xtradb/dict/dict0dict.cc | 57 +++++++++++++++++-----------
storage/xtradb/handler/xtradb_i_s.cc | 5 ++-
storage/xtradb/include/dict0dict.h | 10 +++--
storage/xtradb/srv/srv0srv.cc | 10 +++--
7 files changed, 94 insertions(+), 57 deletions(-)
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index b6ca02fa164..be19a3f1e75 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -1365,9 +1365,6 @@ dict_table_add_to_cache(
dict_table_autoinc_restore(table);
ut_ad(dict_lru_validate());
-
- dict_sys->size += mem_heap_get_size(table->heap)
- + strlen(table->name) + 1;
}
/**********************************************************************//**
@@ -1782,9 +1779,6 @@ dict_table_rename_in_cache(
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
table);
- dict_sys->size += strlen(new_name) - strlen(old_name);
- ut_a(dict_sys->size > 0);
-
/* Update the table_name field in indexes */
for (index = dict_table_get_first_index(table);
index != NULL;
@@ -2071,7 +2065,6 @@ dict_table_remove_from_cache_low(
{
dict_foreign_t* foreign;
dict_index_t* index;
- ulint size;
ut_ad(table);
ut_ad(dict_lru_validate());
@@ -2151,12 +2144,6 @@ dict_table_remove_from_cache_low(
trx_free_for_background(trx);
}
- size = mem_heap_get_size(table->heap) + strlen(table->name) + 1;
-
- ut_ad(dict_sys->size >= size);
-
- dict_sys->size -= size;
-
dict_mem_table_free(table);
}
@@ -2692,8 +2679,6 @@ undo_size_ok:
dict_index_is_ibuf(index)
? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE);
- dict_sys->size += mem_heap_get_size(new_index->heap);
-
dict_mem_index_free(index);
return(DB_SUCCESS);
@@ -2710,7 +2695,6 @@ dict_index_remove_from_cache_low(
ibool lru_evict) /*!< in: TRUE if index being evicted
to make room in the table LRU list */
{
- ulint size;
ulint retries = 0;
btr_search_t* info;
@@ -2778,12 +2762,6 @@ dict_index_remove_from_cache_low(
/* Remove the index from the list of indexes of the table */
UT_LIST_REMOVE(indexes, table->indexes, index);
- size = mem_heap_get_size(index->heap);
-
- ut_ad(dict_sys->size >= size);
-
- dict_sys->size -= size;
-
dict_mem_index_free(index);
}
@@ -7258,3 +7236,38 @@ dict_tf_to_row_format_string(
return(0);
}
#endif /* !UNIV_HOTBACKUP */
+
+/** Calculate the used memory occupied by the data dictionary
+table and index objects.
+@return number of bytes occupied. */
+UNIV_INTERN
+ulint
+dict_sys_get_size()
+{
+ ulint size = 0;
+
+ ut_ad(dict_sys);
+
+ mutex_enter(&dict_sys->mutex);
+
+ for(ulint i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
+ dict_table_t* table;
+
+ for (table = static_cast(HASH_GET_FIRST(dict_sys->table_hash,i));
+ table != NULL;
+ table = static_cast(HASH_GET_NEXT(name_hash, table))) {
+ dict_index_t* index;
+ size += mem_heap_get_size(table->heap) + strlen(table->name) +1;
+
+ for(index = dict_table_get_first_index(table);
+ index != NULL;
+ index = dict_table_get_next_index(index)) {
+ size += mem_heap_get_size(index->heap);
+ }
+ }
+ }
+
+ mutex_exit(&dict_sys->mutex);
+
+ return (size);
+}
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 7c00ac096cb..bee291910ed 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -1614,9 +1614,6 @@ struct dict_sys_t{
on name */
hash_table_t* table_id_hash; /*!< hash table of the tables, based
on id */
- ulint size; /*!< varying space in bytes occupied
- by the data dictionary table and
- index objects */
dict_table_t* sys_tables; /*!< SYS_TABLES table */
dict_table_t* sys_columns; /*!< SYS_COLUMNS table */
dict_table_t* sys_indexes; /*!< SYS_INDEXES table */
@@ -1861,6 +1858,13 @@ dict_table_get_index_on_first_col(
ulint col_index); /*!< in: position of column
in table */
+/** Calculate the used memory occupied by the data dictionary
+table and index objects.
+@return number of bytes occupied. */
+UNIV_INTERN
+ulint
+dict_sys_get_size();
+
#endif /* !UNIV_HOTBACKUP */
#ifndef UNIV_NONINL
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 10baf546e5b..e552e54846f 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1283,7 +1283,7 @@ srv_printf_innodb_monitor(
ut_total_allocated_memory,
mem_pool_get_reserved(mem_comm_pool));
fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
- dict_sys->size);
+ dict_sys_get_size());
buf_print_io(file);
diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc
index 108bdd8f60b..567d24cd89d 100644
--- a/storage/xtradb/dict/dict0dict.cc
+++ b/storage/xtradb/dict/dict0dict.cc
@@ -1374,9 +1374,6 @@ dict_table_add_to_cache(
dict_table_autoinc_restore(table);
ut_ad(dict_lru_validate());
-
- dict_sys->size += mem_heap_get_size(table->heap)
- + strlen(table->name) + 1;
}
/**********************************************************************//**
@@ -1791,9 +1788,6 @@ dict_table_rename_in_cache(
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
table);
- dict_sys->size += strlen(new_name) - strlen(old_name);
- ut_a(dict_sys->size > 0);
-
/* Update the table_name field in indexes */
for (index = dict_table_get_first_index(table);
index != NULL;
@@ -2080,7 +2074,6 @@ dict_table_remove_from_cache_low(
{
dict_foreign_t* foreign;
dict_index_t* index;
- ulint size;
ut_ad(table);
ut_ad(dict_lru_validate());
@@ -2160,12 +2153,6 @@ dict_table_remove_from_cache_low(
trx_free_for_background(trx);
}
- size = mem_heap_get_size(table->heap) + strlen(table->name) + 1;
-
- ut_ad(dict_sys->size >= size);
-
- dict_sys->size -= size;
-
dict_mem_table_free(table);
}
@@ -2701,8 +2688,6 @@ undo_size_ok:
dict_index_is_ibuf(index)
? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE);
- dict_sys->size += mem_heap_get_size(new_index->heap);
-
dict_mem_index_free(index);
return(DB_SUCCESS);
@@ -2719,7 +2704,6 @@ dict_index_remove_from_cache_low(
ibool lru_evict) /*!< in: TRUE if index being evicted
to make room in the table LRU list */
{
- ulint size;
ulint retries = 0;
btr_search_t* info;
@@ -2788,12 +2772,6 @@ dict_index_remove_from_cache_low(
/* Remove the index from the list of indexes of the table */
UT_LIST_REMOVE(indexes, table->indexes, index);
- size = mem_heap_get_size(index->heap);
-
- ut_ad(dict_sys->size >= size);
-
- dict_sys->size -= size;
-
dict_mem_index_free(index);
}
@@ -7296,3 +7274,38 @@ dict_tf_to_row_format_string(
return(0);
}
#endif /* !UNIV_HOTBACKUP */
+
+/** Calculate the used memory occupied by the data dictionary
+table and index objects.
+@return number of bytes occupied. */
+UNIV_INTERN
+ulint
+dict_sys_get_size()
+{
+ ulint size = 0;
+
+ ut_ad(dict_sys);
+
+ mutex_enter(&dict_sys->mutex);
+
+ for(ulint i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
+ dict_table_t* table;
+
+ for (table = static_cast(HASH_GET_FIRST(dict_sys->table_hash,i));
+ table != NULL;
+ table = static_cast(HASH_GET_NEXT(name_hash, table))) {
+ dict_index_t* index;
+ size += mem_heap_get_size(table->heap) + strlen(table->name) +1;
+
+ for(index = dict_table_get_first_index(table);
+ index != NULL;
+ index = dict_table_get_next_index(index)) {
+ size += mem_heap_get_size(index->heap);
+ }
+ }
+ }
+
+ mutex_exit(&dict_sys->mutex);
+
+ return (size);
+}
diff --git a/storage/xtradb/handler/xtradb_i_s.cc b/storage/xtradb/handler/xtradb_i_s.cc
index 84c1e5852bc..6ae32d24c92 100644
--- a/storage/xtradb/handler/xtradb_i_s.cc
+++ b/storage/xtradb/handler/xtradb_i_s.cc
@@ -401,19 +401,20 @@ static int xtradb_internal_hash_tables_fill_table(THD* thd, TABLE_LIST* tables,
if (dict_sys)
{
+ ulint dict_size = dict_sys_get_size();
OK(field_store_string(fields[INT_HASH_TABLES_NAME],
"Dictionary Cache"));
OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],
((dict_sys->table_hash->n_cells
+ dict_sys->table_id_hash->n_cells
) * sizeof(hash_cell_t)
- + dict_sys->size)));
+ + dict_size)));
OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],
((dict_sys->table_hash->n_cells
+ dict_sys->table_id_hash->n_cells
) * sizeof(hash_cell_t))));
OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE],
- dict_sys->size));
+ dict_size));
OK(schema_table_store_record(thd, table));
}
diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h
index ef6c32b1787..33edab3ae98 100644
--- a/storage/xtradb/include/dict0dict.h
+++ b/storage/xtradb/include/dict0dict.h
@@ -1617,9 +1617,6 @@ struct dict_sys_t{
on name */
hash_table_t* table_id_hash; /*!< hash table of the tables, based
on id */
- ulint size; /*!< varying space in bytes occupied
- by the data dictionary table and
- index objects */
dict_table_t* sys_tables; /*!< SYS_TABLES table */
dict_table_t* sys_columns; /*!< SYS_COLUMNS table */
dict_table_t* sys_indexes; /*!< SYS_INDEXES table */
@@ -1863,6 +1860,13 @@ dict_table_get_index_on_first_col(
ulint col_index); /*!< in: position of column
in table */
+/** Calculate the used memory occupied by the data dictionary
+table and index objects.
+@return number of bytes occupied. */
+UNIV_INTERN
+ulint
+dict_sys_get_size();
+
#endif /* !UNIV_HOTBACKUP */
/*************************************************************************
set is_corrupt flag by space_id*/
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index e11697081c6..6a119756401 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -1520,6 +1520,8 @@ srv_printf_innodb_monitor(
recv_sys_subtotal = ((recv_sys && recv_sys->addr_hash)
? mem_heap_get_size(recv_sys->heap) : 0);
+ ulint dict_size = dict_sys ? dict_sys_get_size() : 0;
+
fprintf(file,
"Internal hash tables (constant factor + variable factor)\n"
" Adaptive hash index %lu \t(%lu + " ULINTPF ")\n"
@@ -1538,11 +1540,11 @@ srv_printf_innodb_monitor(
(ulong) (dict_sys ? ((dict_sys->table_hash->n_cells
+ dict_sys->table_id_hash->n_cells
) * sizeof(hash_cell_t)
- + dict_sys->size) : 0),
+ + dict_size) : 0),
(ulong) (dict_sys ? ((dict_sys->table_hash->n_cells
+ dict_sys->table_id_hash->n_cells
) * sizeof(hash_cell_t)) : 0),
- dict_sys ? (dict_sys->size) : 0,
+ dict_size,
(ulong) (fil_system_hash_cells() * sizeof(hash_cell_t)
+ fil_system_hash_nodes()),
@@ -1563,7 +1565,7 @@ srv_printf_innodb_monitor(
fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
- dict_sys ? dict_sys->size : 0);
+ dict_sys ? dict_sys_get_size() : 0);
buf_print_io(file);
@@ -1719,7 +1721,7 @@ srv_export_innodb_status(void)
mem_dictionary = (dict_sys ? ((dict_sys->table_hash->n_cells
+ dict_sys->table_id_hash->n_cells
) * sizeof(hash_cell_t)
- + dict_sys->size) : 0);
+ + dict_sys_get_size()) : 0);
mutex_enter(&srv_innodb_monitor_mutex);
From 2ce3f95151a424f950be40140c45b0ba583e07ab Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Sat, 22 Jul 2017 13:10:10 +0200
Subject: [PATCH 073/101] Connect engine is Gamma
---
storage/connect/ha_connect.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index c30ab9adf4e..89dc1502656 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -7083,6 +7083,6 @@ maria_declare_plugin(connect)
NULL, /* status variables */
connect_system_variables, /* system variables */
"1.06.0001", /* string version */
- MariaDB_PLUGIN_MATURITY_BETA /* maturity */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
}
maria_declare_plugin_end;
From 2804a3fac47a418bd4495463e25fc5c10b7f3e76 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Thu, 27 Jul 2017 12:42:21 +0200
Subject: [PATCH 074/101] memory leak: add a missing end_relay_log_info()
---
sql/rpl_mi.cc | 1 +
1 file changed, 1 insertion(+)
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index 7cb093c9026..c810e030bf2 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -747,6 +747,7 @@ void free_key_master_info(Master_info *mi)
/* We use 2 here instead of 1 just to make it easier when debugging */
mi->killed= 2;
end_master_info(mi);
+ end_relay_log_info(&mi->rli);
mi->unlock_slave_threads();
delete mi;
From 496cea45e2fa56f7a4e28bf0e550362c4fc071e5 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Thu, 27 Jul 2017 12:42:40 +0200
Subject: [PATCH 075/101] update error messages for 10.0
---
mysql-test/suite/rpl/r/rpl_reset_slave_fail.result | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mysql-test/suite/rpl/r/rpl_reset_slave_fail.result b/mysql-test/suite/rpl/r/rpl_reset_slave_fail.result
index fdfec62058f..205e8fe428b 100644
--- a/mysql-test/suite/rpl/r/rpl_reset_slave_fail.result
+++ b/mysql-test/suite/rpl/r/rpl_reset_slave_fail.result
@@ -15,9 +15,9 @@ include/rpl_stop_server.inc [server_number=2]
# Removing file(s)
include/rpl_start_server.inc [server_number=2]
START SLAVE;
-ERROR HY000: Could not initialize master info structure; more error messages can be found in the MariaDB error log
+ERROR HY000: Could not initialize master info structure for ''; more error messages can be found in the MariaDB error log
START SLAVE;
-ERROR HY000: Could not initialize master info structure; more error messages can be found in the MariaDB error log
+ERROR HY000: Could not initialize master info structure for ''; more error messages can be found in the MariaDB error log
RESET SLAVE;
DROP TABLE t1;
START SLAVE UNTIL MASTER_LOG_FILE= 'MASTER_LOG_FILE', MASTER_LOG_POS= MASTER_LOG_POS;;
From c784277590bad3a0d869ca51c03cbce897125924 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Thu, 27 Jul 2017 12:43:03 +0200
Subject: [PATCH 076/101] move the error message where it belongs
---
sql/slave.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sql/slave.cc b/sql/slave.cc
index b00bee5acee..45af5fcd337 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -385,6 +385,7 @@ int init_slave()
{
delete active_mi;
active_mi= 0;
+ sql_print_error("Failed to allocate memory for the Master Info structure");
goto err;
}
@@ -446,7 +447,6 @@ end:
DBUG_RETURN(error);
err:
- sql_print_error("Failed to allocate memory for the Master Info structure");
error= 1;
goto end;
}
From 7134afa22e3ce91b8f729eaa01dae54e93947f71 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Thu, 27 Jul 2017 12:43:45 +0200
Subject: [PATCH 077/101] MYSQL_BIN_LOG::open/close must be under LOCK_log
---
sql/rpl_rli.cc | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index 9e20775a1aa..083e3649505 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -256,8 +256,8 @@ a file name for --relay-log-index option", opt_relaylog_index_name);
if ((info_fd= mysql_file_open(key_file_relay_log_info,
fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
{
- sql_print_error("Failed to create a new relay log info file (\
-file '%s', errno %d)", fname, my_errno);
+ sql_print_error("Failed to create a new relay log info file ("
+ "file '%s', errno %d)", fname, my_errno);
msg= current_thd->get_stmt_da()->message();
goto err;
}
@@ -450,7 +450,9 @@ err:
if (info_fd >= 0)
mysql_file_close(info_fd, MYF(0));
rli->info_fd= -1;
+ mysql_mutex_lock(rli->relay_log.get_log_lock());
rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
+ mysql_mutex_unlock(rli->relay_log.get_log_lock());
mysql_mutex_unlock(&rli->data_lock);
DBUG_RETURN(1);
}
@@ -1145,14 +1147,17 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
"log index file:%s.", rli->relay_log.get_index_fname());
DBUG_RETURN(1);
}
+ mysql_mutex_lock(rli->relay_log.get_log_lock());
if (rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND,
(rli->max_relay_log_size ? rli->max_relay_log_size :
max_binlog_size), 1, TRUE))
{
sql_print_error("Unable to purge relay log files. Failed to open relay "
"log file:%s.", rli->relay_log.get_log_fname());
+ mysql_mutex_unlock(rli->relay_log.get_log_lock());
DBUG_RETURN(1);
}
+ mysql_mutex_unlock(rli->relay_log.get_log_lock());
}
else
DBUG_RETURN(0);
@@ -1210,7 +1215,11 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
}
if (!rli->inited && rli->error_on_rli_init_info)
+ {
+ mysql_mutex_lock(rli->relay_log.get_log_lock());
rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
+ mysql_mutex_unlock(rli->relay_log.get_log_lock());
+ }
err:
#ifndef DBUG_OFF
char buf[22];
From af40426fcdacfa9e8e2868cf5d95ce671c1287a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Thu, 27 Jul 2017 16:20:26 +0300
Subject: [PATCH 078/101] Fix purge_relay_logs post merge
slave_skip_counter must not be reset to 0 during purge_relay_logs. See
MDEV-4937 as to when this change happened.
---
sql/rpl_rli.cc | 1 -
1 file changed, 1 deletion(-)
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index 083e3649505..eac4149cb06 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -1167,7 +1167,6 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
DBUG_ASSERT(rli->slave_running == 0);
DBUG_ASSERT(rli->mi->slave_running == 0);
}
- rli->slave_skip_counter=0;
mysql_mutex_lock(&rli->data_lock);
/*
From d36bd69790c5b27007800964cc1a8bebd9ac7fc2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Sat, 29 Jul 2017 19:59:51 +0300
Subject: [PATCH 079/101] 5.6.37
---
storage/innobase/api/api0api.cc | 21 +++-
storage/innobase/handler/ha_innodb.cc | 21 ++++
storage/innobase/handler/ha_innodb.h | 6 +-
storage/innobase/include/row0mysql.h | 7 +-
storage/innobase/include/row0sel.h | 14 ++-
storage/innobase/row/row0merge.cc | 6 +-
storage/innobase/row/row0sel.cc | 153 +++++++++++++++++++-------
7 files changed, 176 insertions(+), 52 deletions(-)
diff --git a/storage/innobase/api/api0api.cc b/storage/innobase/api/api0api.cc
index 07eecdc46d0..d01b221d71c 100644
--- a/storage/innobase/api/api0api.cc
+++ b/storage/innobase/api/api0api.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2008, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2008, 2017, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -1976,11 +1976,14 @@ ib_cursor_read_row(
page_format = static_cast(
dict_table_is_comp(tuple->index->table));
+
rec = btr_pcur_get_rec(pcur);
- if (prebuilt->innodb_api_rec &&
- prebuilt->innodb_api_rec != rec) {
- rec = prebuilt->innodb_api_rec;
+ if (!rec_get_deleted_flag(rec, page_format)) {
+ if (prebuilt->innodb_api &&
+ prebuilt->innodb_api_rec != NULL) {
+ rec =prebuilt->innodb_api_rec;
+ }
}
if (!rec_get_deleted_flag(rec, page_format)) {
@@ -2017,6 +2020,10 @@ ib_cursor_position(
buf = static_cast(mem_alloc(UNIV_PAGE_SIZE));
+ if (prebuilt->innodb_api) {
+ prebuilt->cursor_heap = cursor->heap;
+ }
+
/* We want to position at one of the ends, row_search_for_mysql()
uses the search_tuple fields to work out what to do. */
dtuple_set_n_fields(prebuilt->search_tuple, 0);
@@ -2071,6 +2078,9 @@ ib_cursor_next(
row_prebuilt_t* prebuilt = cursor->prebuilt;
byte buf[UNIV_PAGE_SIZE_MAX];
+ if (prebuilt->innodb_api) {
+ prebuilt->cursor_heap = cursor->heap;
+ }
/* We want to move to the next record */
dtuple_set_n_fields(prebuilt->search_tuple, 0);
@@ -2123,6 +2133,9 @@ ib_cursor_moveto(
buf = static_cast(mem_alloc(UNIV_PAGE_SIZE));
+ if (prebuilt->innodb_api) {
+ prebuilt->cursor_heap = cursor->heap;
+ }
err = static_cast(row_search_for_mysql(
buf, ib_srch_mode, prebuilt, cursor->match_mode, 0));
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 7843c328bc8..0c02c6808ff 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -8321,6 +8321,27 @@ ha_innobase::ft_init_ext(
return((FT_INFO*) fts_hdl);
}
+/*****************************************************************//**
+Copy a cached MySQL row.
+If requested, also avoids overwriting non-read columns.
+@param[out] buf Row in MySQL format.
+@param[in] cached_row Which row to copy.
+@param[in] rec_len Record length. */
+void
+ha_innobase::copy_cached_row(
+ uchar* buf,
+ const uchar* cached_row,
+ uint rec_len)
+{
+ if (prebuilt->keep_other_fields_on_keyread) {
+ row_sel_copy_cached_fields_for_mysql(buf, cached_row,
+ prebuilt);
+ } else {
+ memcpy(buf, cached_row, rec_len);
+ }
+}
+
+
/*****************************************************************//**
Set up search tuple for a query through FTS_DOC_ID_INDEX on
supplied Doc ID. This is used by MySQL to retrieve the documents
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 4b1cc3ed0bd..1ac6c52dce6 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -142,6 +142,10 @@ class ha_innobase: public handler
int index_first(uchar * buf);
int index_last(uchar * buf);
+ /* Copy a cached MySQL row. If requested, also avoids
+ overwriting non-read columns. */
+ void copy_cached_row(uchar *to_rec, const uchar *from_rec,
+ uint rec_length);
int rnd_init(bool scan);
int rnd_end();
int rnd_next(uchar *buf);
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index d0c1bdaa585..c648332c0ee 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -723,6 +723,8 @@ struct row_prebuilt_t {
mem_heap_t* heap; /*!< memory heap from which
these auxiliary structures are
allocated when needed */
+ mem_heap_t* cursor_heap; /*!< memory heap from which
+ innodb_api_buf is allocated per session*/
ins_node_t* ins_node; /*!< Innobase SQL insert node
used to perform inserts
to the table */
@@ -873,6 +875,9 @@ struct row_prebuilt_t {
unsigned innodb_api:1; /*!< whether this is a InnoDB API
query */
const rec_t* innodb_api_rec; /*!< InnoDB API search result */
+ void* innodb_api_buf; /*!< Buffer holding copy of the physical
+ Innodb API search record */
+ ulint innodb_api_rec_size; /*!< Size of the Innodb API record */
byte* srch_key_val1; /*!< buffer used in converting
search key values from MySQL format
to InnoDB format.*/
diff --git a/storage/innobase/include/row0sel.h b/storage/innobase/include/row0sel.h
index fd5bc755a22..afeb216c2a2 100644
--- a/storage/innobase/include/row0sel.h
+++ b/storage/innobase/include/row0sel.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -205,6 +205,18 @@ struct sel_buf_t{
when data != NULL */
};
+/** Copy used fields from cached row.
+Copy cache record field by field, don't touch fields that
+are not covered by current key.
+@param[out] buf Where to copy the MySQL row.
+@param[in] cached_rec What to copy (in MySQL row format).
+@param[in] prebuilt prebuilt struct. */
+void
+row_sel_copy_cached_fields_for_mysql(
+ byte* buf,
+ const byte* cached_rec,
+ row_prebuilt_t* prebuilt);
+
/** Query plan */
struct plan_t{
dict_table_t* table; /*!< table struct in the dictionary
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 2d63352feaf..4a6fb763da6 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -1462,6 +1462,8 @@ row_merge_read_clustered_index(
row_ext_t* ext;
page_cur_t* cur = btr_pcur_get_page_cur(&pcur);
+ mem_heap_empty(row_heap);
+
page_cur_move_to_next(cur);
if (page_cur_is_after_last(cur)) {
@@ -1885,8 +1887,6 @@ write_buffers:
if (err != DB_SUCCESS) {
goto func_exit;
}
-
- mem_heap_empty(row_heap);
}
func_exit:
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index c53c1154f60..f321e0ba94a 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -2555,47 +2555,51 @@ row_sel_store_row_id_to_prebuilt(
#ifdef UNIV_DEBUG
/** Convert a non-SQL-NULL field from Innobase format to MySQL format. */
-# define row_sel_field_store_in_mysql_format(dest,templ,idx,field,src,len) \
- row_sel_field_store_in_mysql_format_func(dest,templ,idx,field,src,len)
+# define row_sel_field_store_in_mysql_format(dest,templ,idx,field,src,len,sec) \
+ row_sel_field_store_in_mysql_format_func(dest,templ,idx,field,src,len,sec)
#else /* UNIV_DEBUG */
/** Convert a non-SQL-NULL field from Innobase format to MySQL format. */
-# define row_sel_field_store_in_mysql_format(dest,templ,idx,field,src,len) \
- row_sel_field_store_in_mysql_format_func(dest,templ,src,len)
+# define row_sel_field_store_in_mysql_format(dest,templ,idx,field,src,len,sec) \
+ row_sel_field_store_in_mysql_format_func(dest,templ,src,len,sec)
#endif /* UNIV_DEBUG */
-/**************************************************************//**
-Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
-function is row_mysql_store_col_in_innobase_format() in row0mysql.cc. */
+/** Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
+function is row_mysql_store_col_in_innobase_format() in row0mysql.cc.
+@param[in,out] dest buffer where to store; NOTE
+ that BLOBs are not in themselves stored
+ here: the caller must allocate and copy
+ the BLOB into buffer before, and pass
+ the pointer to the BLOB in 'data'
+@param[in] templ MySQL column template. Its following fields
+ are referenced: type, is_unsigned, mysql_col_len,
+ mbminlen, mbmaxlen
+@param[in] index InnoDB index
+@param[in] field_no templ->rec_field_no or templ->clust_rec_field_no
+ or templ->icp_rec_field_no
+@param[in] data data to store
+@param[in] len length of the data
+@param[in] sec_field secondary index field no if the secondary index
+ record but the prebuilt template is in
+ clustered index format and used only for end
+ range comparison. */
static MY_ATTRIBUTE((nonnull))
void
row_sel_field_store_in_mysql_format_func(
-/*=====================================*/
- byte* dest, /*!< in/out: buffer where to store; NOTE
- that BLOBs are not in themselves
- stored here: the caller must allocate
- and copy the BLOB into buffer before,
- and pass the pointer to the BLOB in
- 'data' */
+ byte* dest,
const mysql_row_templ_t* templ,
- /*!< in: MySQL column template.
- Its following fields are referenced:
- type, is_unsigned, mysql_col_len,
- mbminlen, mbmaxlen */
#ifdef UNIV_DEBUG
const dict_index_t* index,
- /*!< in: InnoDB index */
ulint field_no,
- /*!< in: templ->rec_field_no or
- templ->clust_rec_field_no or
- templ->icp_rec_field_no */
#endif /* UNIV_DEBUG */
- const byte* data, /*!< in: data to store */
- ulint len) /*!< in: length of the data */
+ const byte* data,
+ ulint len,
+ ulint sec_field)
{
byte* ptr;
#ifdef UNIV_DEBUG
const dict_field_t* field
= dict_index_get_nth_field(index, field_no);
+ bool clust_templ_for_sec = (sec_field != ULINT_UNDEFINED);
#endif /* UNIV_DEBUG */
ut_ad(len != UNIV_SQL_NULL);
@@ -2709,7 +2713,8 @@ row_sel_field_store_in_mysql_format_func(
containing UTF-8 ENUM columns due to Bug #9526. */
ut_ad(!templ->mbmaxlen
|| !(templ->mysql_col_len % templ->mbmaxlen));
- ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len
+ ut_ad(clust_templ_for_sec
+ || len * templ->mbmaxlen >= templ->mysql_col_len
|| (field_no == templ->icp_rec_field_no
&& field->prefix_len > 0));
ut_ad(!(field->prefix_len % templ->mbmaxlen));
@@ -2737,21 +2742,26 @@ row_sel_field_store_in_mysql_format_func(
case DATA_DECIMAL:
/* Above are the valid column types for MySQL data. */
#endif /* UNIV_DEBUG */
+ /* If sec_field value is present then mapping of
+ secondary index records to clustered index template
+ happens for end range comparison. So length can
+ vary according to secondary index record length. */
ut_ad(field->prefix_len
? field->prefix_len == len
- : templ->mysql_col_len == len);
+ : (clust_templ_for_sec ?
+ 1 : (templ->mysql_col_len == len)));
memcpy(dest, data, len);
}
}
#ifdef UNIV_DEBUG
/** Convert a field from Innobase format to MySQL format. */
-# define row_sel_store_mysql_field(m,p,r,i,o,f,t,c) \
- row_sel_store_mysql_field_func(m,p,r,i,o,f,t,c)
+# define row_sel_store_mysql_field(m,p,r,i,o,f,t,s) \
+ row_sel_store_mysql_field_func(m,p,r,i,o,f,t,s)
#else /* UNIV_DEBUG */
/** Convert a field from Innobase format to MySQL format. */
-# define row_sel_store_mysql_field(m,p,r,i,o,f,t,c) \
- row_sel_store_mysql_field_func(m,p,r,o,f,t,c)
+# define row_sel_store_mysql_field(m,p,r,i,o,f,t,s) \
+ row_sel_store_mysql_field_func(m,p,r,o,f,t,s)
#endif /* UNIV_DEBUG */
/** Convert a field in the Innobase format to a field in the MySQL format.
@param[out] mysql_rec record in the MySQL format
@@ -2766,7 +2776,7 @@ row_sel_field_store_in_mysql_format_func(
or sec field no if clust_templ_for_sec
is TRUE
@param[in] templ row template
-@param[in] clust_templ_for_sec TRUE if rec belongs to secondary index
+@param[in] sec_field_no field_no if rec belongs to secondary index
but prebuilt template is in clustered
index format and used only for end
range comparison. */
@@ -2782,10 +2792,12 @@ row_sel_store_mysql_field_func(
const ulint* offsets,
ulint field_no,
const mysql_row_templ_t*templ,
- bool clust_templ_for_sec)
+ ulint sec_field_no)
{
const byte* data;
ulint len;
+ ulint clust_field_no;
+ bool clust_templ_for_sec = (sec_field_no != ULINT_UNDEFINED);
ut_ad(prebuilt->default_rec);
ut_ad(templ);
@@ -2796,7 +2808,14 @@ row_sel_store_mysql_field_func(
|| field_no == templ->rec_field_no
|| field_no == templ->icp_rec_field_no);
ut_ad(rec_offs_validate(rec,
- clust_templ_for_sec == true ? prebuilt->index : index, offsets));
+ clust_templ_for_sec ? prebuilt->index : index, offsets));
+
+ /* If sec_field_no is present then extract the data from record
+ using secondary field no. */
+ if (clust_templ_for_sec) {
+ clust_field_no = field_no;
+ field_no = sec_field_no;
+ }
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) {
@@ -2845,7 +2864,8 @@ row_sel_store_mysql_field_func(
row_sel_field_store_in_mysql_format(
mysql_rec + templ->mysql_col_offset,
- templ, index, field_no, data, len);
+ templ, index, field_no, data, len,
+ ULINT_UNDEFINED);
if (heap != prebuilt->blob_heap) {
mem_heap_free(heap);
@@ -2893,9 +2913,14 @@ row_sel_store_mysql_field_func(
mem_heap_dup(prebuilt->blob_heap, data, len));
}
+ /* Reassign the clustered index field no. */
+ if (clust_templ_for_sec) {
+ field_no = clust_field_no;
+ }
+
row_sel_field_store_in_mysql_format(
mysql_rec + templ->mysql_col_offset,
- templ, index, field_no, data, len);
+ templ, index, field_no, data, len, sec_field_no);
}
ut_ad(len != UNIV_SQL_NULL);
@@ -2967,6 +2992,8 @@ row_sel_store_mysql_rec(
= rec_clust
? templ->clust_rec_field_no
: templ->rec_field_no;
+ ulint sec_field_no = ULINT_UNDEFINED;
+
/* We should never deliver column prefixes to MySQL,
except for evaluating innobase_index_cond(). */
ut_ad(dict_index_get_nth_field(index, field_no)->prefix_len
@@ -2983,13 +3010,13 @@ row_sel_store_mysql_rec(
ut_ad(templ->rec_field_no == templ->clust_rec_field_no);
- field_no = it - template_col.begin();
+ sec_field_no = it - template_col.begin();
}
if (!row_sel_store_mysql_field(mysql_rec, prebuilt,
rec, index, offsets,
field_no, templ,
- clust_templ_for_sec)) {
+ sec_field_no)) {
return(FALSE);
}
}
@@ -2999,7 +3026,8 @@ row_sel_store_mysql_rec(
NOTE, the record must be cluster index record. Secondary index
might not have the Doc ID */
if (dict_table_has_fts_index(prebuilt->table)
- && dict_index_is_clust(index)) {
+ && dict_index_is_clust(index)
+ && !clust_templ_for_sec) {
prebuilt->fts_doc_id = fts_get_doc_id_from_rec(
prebuilt->table, rec, NULL);
@@ -3370,6 +3398,36 @@ row_sel_copy_cached_field_for_mysql(
ut_memcpy(buf, cache, len);
}
+/** Copy used fields from cached row.
+Copy cache record field by field, don't touch fields that
+are not covered by current key.
+@param[out] buf Where to copy the MySQL row.
+@param[in] cached_rec What to copy (in MySQL row format).
+@param[in] prebuilt prebuilt struct. */
+void
+row_sel_copy_cached_fields_for_mysql(
+ byte* buf,
+ const byte* cached_rec,
+ row_prebuilt_t* prebuilt)
+{
+ const mysql_row_templ_t*templ;
+ ulint i;
+ for (i = 0; i < prebuilt->n_template; i++) {
+ templ = prebuilt->mysql_template + i;
+
+ row_sel_copy_cached_field_for_mysql(
+ buf, cached_rec, templ);
+ /* Copy NULL bit of the current field from cached_rec
+ to buf */
+ if (templ->mysql_null_bit_mask) {
+ buf[templ->mysql_null_byte_offset]
+ ^= (buf[templ->mysql_null_byte_offset]
+ ^ cached_rec[templ->mysql_null_byte_offset])
+ & (byte) templ->mysql_null_bit_mask;
+ }
+ }
+}
+
/********************************************************************//**
Pops a cached row for MySQL from the fetch cache. */
UNIV_INLINE
@@ -3629,7 +3687,7 @@ row_search_idx_cond_check(
if (!row_sel_store_mysql_field(mysql_rec, prebuilt,
rec, prebuilt->index, offsets,
templ->icp_rec_field_no,
- templ, false)) {
+ templ, ULINT_UNDEFINED)) {
return(ICP_NO_MATCH);
}
}
@@ -5086,8 +5144,19 @@ idx_cond_failed:
btr_pcur_store_position(pcur, &mtr);
- if (prebuilt->innodb_api) {
- prebuilt->innodb_api_rec = result_rec;
+ if (prebuilt->innodb_api
+ && (btr_pcur_get_rec(pcur) != result_rec)) {
+ ulint rec_size = rec_offs_size(offsets);
+ if (!prebuilt->innodb_api_rec_size ||
+ (prebuilt->innodb_api_rec_size < rec_size)) {
+ prebuilt->innodb_api_buf =
+ static_cast
+ (mem_heap_alloc(prebuilt->cursor_heap,rec_size));
+ prebuilt->innodb_api_rec_size = rec_size;
+ }
+ prebuilt->innodb_api_rec =
+ rec_copy(
+ prebuilt->innodb_api_buf, result_rec, offsets);
}
}
From 2160a851840488d38358d5633237ec197fab969b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Fri, 28 Jul 2017 20:47:12 +0300
Subject: [PATCH 080/101] Update subselect test results to pass on 10.0
One query was removed due to inconsistent behaviour with subquery cache
enabled vs disabled. MDEV-13399 has been created to track this change
and fix.
---
mysql-test/r/subselect.result | 9 ++++++++-
mysql-test/r/subselect_no_exists_to_in.result | 15 +++++++++++++++
mysql-test/r/subselect_no_mat.result | 9 ++++++++-
mysql-test/r/subselect_no_opts.result | 9 ++++++++-
mysql-test/r/subselect_no_scache.result | 9 ++++++++-
mysql-test/r/subselect_no_semijoin.result | 9 ++++++++-
mysql-test/t/subselect.test | 9 ++++++++-
7 files changed, 63 insertions(+), 6 deletions(-)
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index ce38d6ee643..3fa7fef89b2 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -7174,8 +7174,15 @@ drop table t1,t2;
CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
INSERT t1 VALUES (4),(8);
CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
-INSERT t2 VALUES (6),(9);
+INSERT t2 VALUES (6);
SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
(SELECT MAX(sq.f2) FROM t1)
NULL
+#
+# Disable this query till MDEV-13399 is resolved
+#
+# INSERT t2 VALUES (9);
+# --error ER_SUBQUERY_NO_1_ROW
+# SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+#
drop table t1, t2;
diff --git a/mysql-test/r/subselect_no_exists_to_in.result b/mysql-test/r/subselect_no_exists_to_in.result
index 8bc3b8c6efb..818fdf6c335 100644
--- a/mysql-test/r/subselect_no_exists_to_in.result
+++ b/mysql-test/r/subselect_no_exists_to_in.result
@@ -7171,6 +7171,21 @@ SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1;
ERROR 21000: Subquery returns more than 1 row
drop view v1;
drop table t1,t2;
+CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
+INSERT t1 VALUES (4),(8);
+CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
+INSERT t2 VALUES (6);
+SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+(SELECT MAX(sq.f2) FROM t1)
+NULL
+#
+# Disable this query till MDEV-13399 is resolved
+#
+# INSERT t2 VALUES (9);
+# --error ER_SUBQUERY_NO_1_ROW
+# SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+#
+drop table t1, t2;
set optimizer_switch=default;
select @@optimizer_switch like '%exists_to_in=off%';
@@optimizer_switch like '%exists_to_in=off%'
diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
index 30dcf56c091..51e3c7066d4 100644
--- a/mysql-test/r/subselect_no_mat.result
+++ b/mysql-test/r/subselect_no_mat.result
@@ -7167,10 +7167,17 @@ drop table t1,t2;
CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
INSERT t1 VALUES (4),(8);
CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
-INSERT t2 VALUES (6),(9);
+INSERT t2 VALUES (6);
SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
(SELECT MAX(sq.f2) FROM t1)
NULL
+#
+# Disable this query till MDEV-13399 is resolved
+#
+# INSERT t2 VALUES (9);
+# --error ER_SUBQUERY_NO_1_ROW
+# SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+#
drop table t1, t2;
set optimizer_switch=default;
select @@optimizer_switch like '%materialization=on%';
diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result
index 62a304a0c74..4a26d641aa6 100644
--- a/mysql-test/r/subselect_no_opts.result
+++ b/mysql-test/r/subselect_no_opts.result
@@ -7165,9 +7165,16 @@ drop table t1,t2;
CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
INSERT t1 VALUES (4),(8);
CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
-INSERT t2 VALUES (6),(9);
+INSERT t2 VALUES (6);
SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
(SELECT MAX(sq.f2) FROM t1)
NULL
+#
+# Disable this query till MDEV-13399 is resolved
+#
+# INSERT t2 VALUES (9);
+# --error ER_SUBQUERY_NO_1_ROW
+# SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+#
drop table t1, t2;
set @optimizer_switch_for_subselect_test=null;
diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result
index d9e3be284f0..39e6a8c26d1 100644
--- a/mysql-test/r/subselect_no_scache.result
+++ b/mysql-test/r/subselect_no_scache.result
@@ -7180,10 +7180,17 @@ drop table t1,t2;
CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
INSERT t1 VALUES (4),(8);
CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
-INSERT t2 VALUES (6),(9);
+INSERT t2 VALUES (6);
SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
(SELECT MAX(sq.f2) FROM t1)
NULL
+#
+# Disable this query till MDEV-13399 is resolved
+#
+# INSERT t2 VALUES (9);
+# --error ER_SUBQUERY_NO_1_ROW
+# SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+#
drop table t1, t2;
set optimizer_switch=default;
select @@optimizer_switch like '%subquery_cache=on%';
diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result
index 839d76ddd0b..6980969bb79 100644
--- a/mysql-test/r/subselect_no_semijoin.result
+++ b/mysql-test/r/subselect_no_semijoin.result
@@ -7165,10 +7165,17 @@ drop table t1,t2;
CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
INSERT t1 VALUES (4),(8);
CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
-INSERT t2 VALUES (6),(9);
+INSERT t2 VALUES (6);
SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
(SELECT MAX(sq.f2) FROM t1)
NULL
+#
+# Disable this query till MDEV-13399 is resolved
+#
+# INSERT t2 VALUES (9);
+# --error ER_SUBQUERY_NO_1_ROW
+# SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+#
drop table t1, t2;
set @optimizer_switch_for_subselect_test=null;
set @join_cache_level_for_subselect_test=NULL;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index cdb278d9130..43373248834 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -6059,6 +6059,13 @@ drop table t1,t2;
CREATE TABLE t1 (f1 INT, KEY(f1)) ENGINE=MyISAM;
INSERT t1 VALUES (4),(8);
CREATE TABLE t2 (f2 INT, KEY(f2)) ENGINE=MyISAM;
-INSERT t2 VALUES (6),(9);
+INSERT t2 VALUES (6);
SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+--echo #
+--echo # Disable this query till MDEV-13399 is resolved
+--echo #
+--echo # INSERT t2 VALUES (9);
+--echo # --error ER_SUBQUERY_NO_1_ROW
+--echo # SELECT (SELECT MAX(sq.f2) FROM t1) FROM (SELECT * FROM t2) AS sq WHERE f2 = 2;
+--echo #
drop table t1, t2;
From e1b5e986485a2e7660468fd3fab80d0085ecba62 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Sun, 30 Jul 2017 11:33:55 +0300
Subject: [PATCH 081/101] 5.6.37 (no-changes)
From 900e3218cfe34cd2a8b730afecce2371c3bf9963 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Sun, 30 Jul 2017 11:35:48 +0300
Subject: [PATCH 082/101] Bump innodb version post merge
---
storage/innobase/include/univ.i | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index 15147f87115..3196df061a1 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -45,7 +45,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 36
+#define INNODB_VERSION_BUGFIX 37
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
From dba454ef54bfc83cc1ade93c668f39ec0a5895d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Sun, 30 Jul 2017 11:53:36 +0300
Subject: [PATCH 083/101] 8.41
---
pcre/CMakeLists.txt | 2 +-
pcre/ChangeLog | 47 +
pcre/NEWS | 6 +
pcre/aclocal.m4 | 16 +-
pcre/config.h.generic | 6 +-
pcre/configure | 40 +-
pcre/configure.ac | 12 +-
pcre/doc/html/pcrejit.html | 57 +-
pcre/doc/html/pcretest.html | 9 +-
pcre/doc/pcre.txt | 49 +-
pcre/doc/pcrejit.3 | 54 +-
pcre/doc/pcretest.1 | 10 +-
pcre/doc/pcretest.txt | 8 +-
pcre/pcre.h.generic | 4 +-
pcre/pcre_compile.c | 16 +-
pcre/pcre_dfa_exec.c | 4 +-
pcre/pcre_exec.c | 2 +-
pcre/pcre_internal.h | 11 +-
pcre/pcre_jit_compile.c | 994 +++++++++----------
pcre/pcre_scanner_unittest.cc | 1 +
pcre/pcre_stringpiece.h.in | 4 +-
pcre/pcre_stringpiece_unittest.cc | 1 +
pcre/pcre_tables.c | 4 +-
pcre/pcre_ucd.c | 14 +
pcre/pcrecpp_unittest.cc | 1 +
pcre/pcregrep.c | 29 +-
pcre/pcreposix.c | 6 +-
pcre/pcretest.c | 17 +-
pcre/sljit/sljitConfig.h | 4 +-
pcre/sljit/sljitConfigInternal.h | 75 +-
pcre/sljit/sljitExecAllocator.c | 12 +-
pcre/sljit/sljitLir.c | 576 +++++++----
pcre/sljit/sljitLir.h | 611 +++++++-----
pcre/sljit/sljitNativeARM_32.c | 1245 ++++++++++--------------
pcre/sljit/sljitNativeARM_64.c | 229 +++--
pcre/sljit/sljitNativeARM_T2_32.c | 854 +++++++---------
pcre/sljit/sljitNativeMIPS_32.c | 271 ++++--
pcre/sljit/sljitNativeMIPS_64.c | 274 ++++--
pcre/sljit/sljitNativeMIPS_common.c | 557 +++++------
pcre/sljit/sljitNativePPC_32.c | 115 ++-
pcre/sljit/sljitNativePPC_64.c | 162 +--
pcre/sljit/sljitNativePPC_common.c | 465 +++++----
pcre/sljit/sljitNativeSPARC_32.c | 27 +-
pcre/sljit/sljitNativeSPARC_common.c | 155 +--
pcre/sljit/sljitNativeTILEGX-encoder.c | 2 +-
pcre/sljit/sljitNativeTILEGX_64.c | 41 +-
pcre/sljit/sljitNativeX86_32.c | 154 ++-
pcre/sljit/sljitNativeX86_64.c | 147 ++-
pcre/sljit/sljitNativeX86_common.c | 783 +++++++--------
pcre/sljit/sljitUtils.c | 69 +-
pcre/testdata/testinput1 | 3 +
pcre/testdata/testinput12 | 2 +
pcre/testdata/testinput15 | 3 +
pcre/testdata/testinput8 | 3 +
pcre/testdata/testoutput1 | 4 +
pcre/testdata/testoutput12 | 2 +
pcre/testdata/testoutput15 | 5 +
pcre/testdata/testoutput8 | 4 +
58 files changed, 4348 insertions(+), 3930 deletions(-)
diff --git a/pcre/CMakeLists.txt b/pcre/CMakeLists.txt
index 42451ad82fd..858a34bd063 100644
--- a/pcre/CMakeLists.txt
+++ b/pcre/CMakeLists.txt
@@ -191,7 +191,7 @@ IF (MINGW)
ENDIF(MINGW)
IF(MSVC)
- OPTION(PCRE_STATIC_RUNTIME OFF CACHE BOOL
+ OPTION(PCRE_STATIC_RUNTIME
"ON=Compile against the static runtime (/MT)."
OFF)
OPTION(INSTALL_MSVC_PDB
diff --git a/pcre/ChangeLog b/pcre/ChangeLog
index 01511b1327c..590a7542885 100644
--- a/pcre/ChangeLog
+++ b/pcre/ChangeLog
@@ -4,6 +4,53 @@ ChangeLog for PCRE
Note that the PCRE 8.xx series (PCRE1) is now in a bugfix-only state. All
development is happening in the PCRE2 10.xx series.
+Version 8.41 05-July-2017
+-------------------------
+
+1. Fixed typo in CMakeLists.txt (wrong number of arguments for
+PCRE_STATIC_RUNTIME (affects MSVC only).
+
+2. Issue 1 for 8.40 below was not correctly fixed. If pcregrep in multiline
+mode with --only-matching matched several lines, it restarted scanning at the
+next line instead of moving on to the end of the matched string, which can be
+several lines after the start.
+
+3. Fix a missing else in the JIT compiler reported by 'idaifish'.
+
+4. A (?# style comment is now ignored between a basic quantifier and a
+following '+' or '?' (example: /X+(?#comment)?Y/.
+
+5. Avoid use of a potentially overflowing buffer in pcregrep (patch by Petr
+Pisar).
+
+6. Fuzzers have reported issues in pcretest. These are NOT serious (it is,
+after all, just a test program). However, to stop the reports, some easy ones
+are fixed:
+
+ (a) Check for values < 256 when calling isprint() in pcretest.
+ (b) Give an error for too big a number after \O.
+
+7. In the 32-bit library in non-UTF mode, an attempt to find a Unicode
+property for a character with a code point greater than 0x10ffff (the Unicode
+maximum) caused a crash.
+
+8. The alternative matching function, pcre_dfa_exec() misbehaved if it
+encountered a character class with a possessive repeat, for example [a-f]{3}+.
+
+9. When pcretest called pcre_copy_substring() in 32-bit mode, it set the buffer
+length incorrectly, which could result in buffer overflow.
+
+10. Remove redundant line of code (accidentally left in ages ago).
+
+11. Applied C++ patch from Irfan Adilovic to guard 'using std::' directives
+with namespace pcrecpp (Bugzilla #2084).
+
+12. Remove a duplication typo in pcre_tables.c.
+
+13. Fix returned offsets from regexec() when REG_STARTEND is used with a
+starting offset greater than zero.
+
+
Version 8.40 11-January-2017
----------------------------
diff --git a/pcre/NEWS b/pcre/NEWS
index b92c4f9605e..36be07cb880 100644
--- a/pcre/NEWS
+++ b/pcre/NEWS
@@ -1,6 +1,12 @@
News about PCRE releases
------------------------
+Release 8.41 13-June-2017
+-------------------------
+
+This is a bug-fix release.
+
+
Release 8.40 11-January-2017
----------------------------
diff --git a/pcre/aclocal.m4 b/pcre/aclocal.m4
index f118a7ea19c..c2b46211930 100644
--- a/pcre/aclocal.m4
+++ b/pcre/aclocal.m4
@@ -20,9 +20,9 @@ You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
-dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
-dnl serial 11 (pkg-config-0.29.1)
-dnl
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+# serial 12 (pkg-config-0.29.2)
+
dnl Copyright © 2004 Scott James Remnant .
dnl Copyright © 2012-2015 Dan Nicholson
dnl
@@ -63,7 +63,7 @@ dnl
dnl See the "Since" comment for each macro you use to see what version
dnl of the macros you require.
m4_defun([PKG_PREREQ],
-[m4_define([PKG_MACROS_VERSION], [0.29.1])
+[m4_define([PKG_MACROS_VERSION], [0.29.2])
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
])dnl PKG_PREREQ
@@ -164,7 +164,7 @@ AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
pkg_failed=no
-AC_MSG_CHECKING([for $1])
+AC_MSG_CHECKING([for $2])
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
@@ -174,11 +174,11 @@ and $1[]_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.])
if test $pkg_failed = yes; then
- AC_MSG_RESULT([no])
+ AC_MSG_RESULT([no])
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
- else
+ else
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
@@ -195,7 +195,7 @@ installed software in a non-standard prefix.
_PKG_TEXT])[]dnl
])
elif test $pkg_failed = untried; then
- AC_MSG_RESULT([no])
+ AC_MSG_RESULT([no])
m4_default([$4], [AC_MSG_FAILURE(
[The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
diff --git a/pcre/config.h.generic b/pcre/config.h.generic
index f09749060cf..3ad45741272 100644
--- a/pcre/config.h.generic
+++ b/pcre/config.h.generic
@@ -235,7 +235,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_NAME "PCRE"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "PCRE 8.40"
+#define PACKAGE_STRING "PCRE 8.41"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre"
@@ -244,7 +244,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "8.40"
+#define PACKAGE_VERSION "8.41"
/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
parentheses (of any kind) in a pattern. This limits the amount of system
@@ -336,7 +336,7 @@ sure both macros are undefined; an emulation function will then be used. */
/* #undef SUPPORT_VALGRIND */
/* Version number of package */
-#define VERSION "8.40"
+#define VERSION "8.41"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
diff --git a/pcre/configure b/pcre/configure
index 42b9638d5ee..6fe8854a94e 100755
--- a/pcre/configure
+++ b/pcre/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for PCRE 8.40.
+# Generated by GNU Autoconf 2.69 for PCRE 8.41.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='PCRE'
PACKAGE_TARNAME='pcre'
-PACKAGE_VERSION='8.40'
-PACKAGE_STRING='PCRE 8.40'
+PACKAGE_VERSION='8.41'
+PACKAGE_STRING='PCRE 8.41'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1418,7 +1418,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures PCRE 8.40 to adapt to many kinds of systems.
+\`configure' configures PCRE 8.41 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1488,7 +1488,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of PCRE 8.40:";;
+ short | recursive ) echo "Configuration of PCRE 8.41:";;
esac
cat <<\_ACEOF
@@ -1662,7 +1662,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-PCRE configure 8.40
+PCRE configure 8.41
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2419,7 +2419,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by PCRE $as_me 8.40, which was
+It was created by PCRE $as_me 8.41, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3283,7 +3283,7 @@ fi
# Define the identity of the package.
PACKAGE='pcre'
- VERSION='8.40'
+ VERSION='8.41'
cat >>confdefs.h <<_ACEOF
@@ -17634,9 +17634,9 @@ _ACEOF
# Versioning
PCRE_MAJOR="8"
-PCRE_MINOR="40"
+PCRE_MINOR="41"
PCRE_PRERELEASE=""
-PCRE_DATE="2017-01-11"
+PCRE_DATE="2017-07-05"
if test "$PCRE_MINOR" = "08" -o "$PCRE_MINOR" = "09"
then
@@ -19658,16 +19658,16 @@ esac
# (Note: The libpcre*_version bits are m4 variables, assigned above)
EXTRA_LIBPCRE_LDFLAGS="$EXTRA_LIBPCRE_LDFLAGS \
- $NO_UNDEFINED -version-info 3:8:2"
+ $NO_UNDEFINED -version-info 3:9:2"
EXTRA_LIBPCRE16_LDFLAGS="$EXTRA_LIBPCRE16_LDFLAGS \
- $NO_UNDEFINED -version-info 2:8:2"
+ $NO_UNDEFINED -version-info 2:9:2"
EXTRA_LIBPCRE32_LDFLAGS="$EXTRA_LIBPCRE32_LDFLAGS \
- $NO_UNDEFINED -version-info 0:8:0"
+ $NO_UNDEFINED -version-info 0:9:0"
EXTRA_LIBPCREPOSIX_LDFLAGS="$EXTRA_LIBPCREPOSIX_LDFLAGS \
- $NO_UNDEFINED -version-info 0:4:0"
+ $NO_UNDEFINED -version-info 0:5:0"
EXTRA_LIBPCRECPP_LDFLAGS="$EXTRA_LIBPCRECPP_LDFLAGS \
$NO_UNDEFINED -version-info 0:1:0 \
@@ -19872,8 +19872,8 @@ $as_echo "no" >&6; }
fi
pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND" >&5
-$as_echo_n "checking for VALGRIND... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for valgrind" >&5
+$as_echo_n "checking for valgrind... " >&6; }
if test -n "$VALGRIND_CFLAGS"; then
pkg_cv_VALGRIND_CFLAGS="$VALGRIND_CFLAGS"
@@ -19913,7 +19913,7 @@ fi
if test $pkg_failed = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -19940,7 +19940,7 @@ Alternatively, you may set the environment variables VALGRIND_CFLAGS
and VALGRIND_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details." "$LINENO" 5
elif test $pkg_failed = untried; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
@@ -20719,7 +20719,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by PCRE $as_me 8.40, which was
+This file was extended by PCRE $as_me 8.41, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20785,7 +20785,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-PCRE config.status 8.40
+PCRE config.status 8.41
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/pcre/configure.ac b/pcre/configure.ac
index 24ef7271e05..718a18508c9 100644
--- a/pcre/configure.ac
+++ b/pcre/configure.ac
@@ -9,18 +9,18 @@ dnl The PCRE_PRERELEASE feature is for identifying release candidates. It might
dnl be defined as -RC2, for example. For real releases, it should be empty.
m4_define(pcre_major, [8])
-m4_define(pcre_minor, [40])
+m4_define(pcre_minor, [41])
m4_define(pcre_prerelease, [])
-m4_define(pcre_date, [2017-01-11])
+m4_define(pcre_date, [2017-07-05])
# NOTE: The CMakeLists.txt file searches for the above variables in the first
# 50 lines of this file. Please update that if the variables above are moved.
# Libtool shared library interface versions (current:revision:age)
-m4_define(libpcre_version, [3:8:2])
-m4_define(libpcre16_version, [2:8:2])
-m4_define(libpcre32_version, [0:8:0])
-m4_define(libpcreposix_version, [0:4:0])
+m4_define(libpcre_version, [3:9:2])
+m4_define(libpcre16_version, [2:9:2])
+m4_define(libpcre32_version, [0:9:0])
+m4_define(libpcreposix_version, [0:5:0])
m4_define(libpcrecpp_version, [0:1:0])
AC_PREREQ(2.57)
diff --git a/pcre/doc/html/pcrejit.html b/pcre/doc/html/pcrejit.html
index 210f1da0262..abb342522f9 100644
--- a/pcre/doc/html/pcrejit.html
+++ b/pcre/doc/html/pcrejit.html
@@ -79,9 +79,12 @@ API that is JIT-specific.
If your program may sometimes be linked with versions of PCRE that are older
-than 8.20, but you want to use JIT when it is available, you can test
-the values of PCRE_MAJOR and PCRE_MINOR, or the existence of a JIT macro such
-as PCRE_CONFIG_JIT, for compile-time control of your code.
+than 8.20, but you want to use JIT when it is available, you can test the
+values of PCRE_MAJOR and PCRE_MINOR, or the existence of a JIT macro such as
+PCRE_CONFIG_JIT, for compile-time control of your code. Also beware that the
+pcre_jit_exec() function was not available at all before 8.32,
+and may not be available at all if PCRE isn't compiled with
+--enable-jit. See the "JIT FAST PATH API" section below for details.
SIMPLE USE OF JIT
@@ -119,6 +122,20 @@ when you call pcre_study():
PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE
PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE
+If using pcre_jit_exec() and supporting a pre-8.32 version of
+PCRE, you can insert:
+
+ #if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32
+ pcre_jit_exec(...);
+ #else
+ pcre_exec(...)
+ #endif
+
+but as described in the "JIT FAST PATH API" section below this assumes
+version 8.32 and later are compiled with --enable-jit, which may
+break.
+
+
The JIT compiler generates different optimized code for each of the three
modes (normal, soft partial, hard partial). When pcre_exec() is called,
the appropriate code is run if it is available. Otherwise, the pattern is
@@ -428,6 +445,36 @@ fast path, and if invalid data is passed, the result is undefined.
Bypassing the sanity checks and the pcre_exec() wrapping can give
speedups of more than 10%.
+
+Note that the pcre_jit_exec() function is not available in versions of
+PCRE before 8.32 (released in November 2012). If you need to support versions
+that old you must either use the slower pcre_exec(), or switch between
+the two codepaths by checking the values of PCRE_MAJOR and PCRE_MINOR.
+
+
+Due to an unfortunate implementation oversight, even in versions 8.32
+and later there will be no pcre_jit_exec() stub function defined
+when PCRE is compiled with --disable-jit, which is the default, and
+there's no way to detect whether PCRE was compiled with --enable-jit
+via a macro.
+
+
+If you need to support versions older than 8.32, or versions that may
+not build with --enable-jit, you must either use the slower
+pcre_exec(), or switch between the two codepaths by checking the
+values of PCRE_MAJOR and PCRE_MINOR.
+
+
+Switching between the two by checking the version assumes that all the
+versions being targeted are built with --enable-jit. To also support
+builds that may use --disable-jit either pcre_exec() must be
+used, or a compile-time check for JIT via pcre_config() (which
+assumes the runtime environment will be the same), or as the Git
+project decided to do, simply assume that pcre_jit_exec() is
+present in 8.32 or later unless a compile-time flag is provided, see
+the "grep: un-break building with PCRE >= 8.32 without --enable-jit"
+commit in git.git for an example of that.
+
SEE ALSO
pcreapi(3)
@@ -443,9 +490,9 @@ Cambridge CB2 3QH, England.
REVISION
-Last updated: 17 March 2013
+Last updated: 05 July 2017
-Copyright © 1997-2013 University of Cambridge.
+Copyright © 1997-2017 University of Cambridge.
Return to the PCRE index page.
diff --git a/pcre/doc/html/pcretest.html b/pcre/doc/html/pcretest.html
index 839fabf189b..ba540d3c385 100644
--- a/pcre/doc/html/pcretest.html
+++ b/pcre/doc/html/pcretest.html
@@ -74,6 +74,11 @@ newline as data characters. However, in some Windows environments character 26
maximum portability, therefore, it is safest to use only ASCII characters in
pcretest input files.
+
+The input is processed using using C's string functions, so must not
+contain binary zeroes, even though in Unix-like environments, fgets()
+treats any bytes other than newline as data characters.
+
PCRE's 8-BIT, 16-BIT AND 32-BIT LIBRARIES
From release 8.30, two separate PCRE libraries can be built. The original one
@@ -1149,9 +1154,9 @@ Cambridge CB2 3QH, England.
REVISION
-Last updated: 09 February 2014
+Last updated: 23 February 2017
-Copyright © 1997-2014 University of Cambridge.
+Copyright © 1997-2017 University of Cambridge.
Return to the PCRE index page.
diff --git a/pcre/doc/pcre.txt b/pcre/doc/pcre.txt
index d68d5033ceb..c027538f500 100644
--- a/pcre/doc/pcre.txt
+++ b/pcre/doc/pcre.txt
@@ -8365,7 +8365,11 @@ AVAILABILITY OF JIT SUPPORT
If your program may sometimes be linked with versions of PCRE that are
older than 8.20, but you want to use JIT when it is available, you can
test the values of PCRE_MAJOR and PCRE_MINOR, or the existence of a JIT
- macro such as PCRE_CONFIG_JIT, for compile-time control of your code.
+ macro such as PCRE_CONFIG_JIT, for compile-time control of your code.
+ Also beware that the pcre_jit_exec() function was not available at all
+ before 8.32, and may not be available at all if PCRE isn't compiled
+ with --enable-jit. See the "JIT FAST PATH API" section below for
+ details.
SIMPLE USE OF JIT
@@ -8407,6 +8411,18 @@ SIMPLE USE OF JIT
PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE
PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE
+ If using pcre_jit_exec() and supporting a pre-8.32 version of PCRE, you
+ can insert:
+
+ #if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32
+ pcre_jit_exec(...);
+ #else
+ pcre_exec(...)
+ #endif
+
+ but as described in the "JIT FAST PATH API" section below this assumes
+ version 8.32 and later are compiled with --enable-jit, which may break.
+
The JIT compiler generates different optimized code for each of the
three modes (normal, soft partial, hard partial). When pcre_exec() is
called, the appropriate code is run if it is available. Otherwise, the
@@ -8696,6 +8712,33 @@ JIT FAST PATH API
Bypassing the sanity checks and the pcre_exec() wrapping can give
speedups of more than 10%.
+ Note that the pcre_jit_exec() function is not available in versions of
+ PCRE before 8.32 (released in November 2012). If you need to support
+ versions that old you must either use the slower pcre_exec(), or switch
+ between the two codepaths by checking the values of PCRE_MAJOR and
+ PCRE_MINOR.
+
+ Due to an unfortunate implementation oversight, even in versions 8.32
+ and later there will be no pcre_jit_exec() stub function defined when
+ PCRE is compiled with --disable-jit, which is the default, and there's
+ no way to detect whether PCRE was compiled with --enable-jit via a
+ macro.
+
+ If you need to support versions older than 8.32, or versions that may
+ not build with --enable-jit, you must either use the slower
+ pcre_exec(), or switch between the two codepaths by checking the values
+ of PCRE_MAJOR and PCRE_MINOR.
+
+ Switching between the two by checking the version assumes that all the
+ versions being targeted are built with --enable-jit. To also support
+ builds that may use --disable-jit either pcre_exec() must be used, or a
+ compile-time check for JIT via pcre_config() (which assumes the runtime
+ environment will be the same), or as the Git project decided to do,
+ simply assume that pcre_jit_exec() is present in 8.32 or later unless a
+ compile-time flag is provided, see the "grep: un-break building with
+ PCRE >= 8.32 without --enable-jit" commit in git.git for an example of
+ that.
+
SEE ALSO
@@ -8711,8 +8754,8 @@ AUTHOR
REVISION
- Last updated: 17 March 2013
- Copyright (c) 1997-2013 University of Cambridge.
+ Last updated: 05 July 2017
+ Copyright (c) 1997-2017 University of Cambridge.
------------------------------------------------------------------------------
diff --git a/pcre/doc/pcrejit.3 b/pcre/doc/pcrejit.3
index 341403f7c84..3b785f0f631 100644
--- a/pcre/doc/pcrejit.3
+++ b/pcre/doc/pcrejit.3
@@ -1,4 +1,4 @@
-.TH PCREJIT 3 "17 March 2013" "PCRE 8.33"
+.TH PCREJIT 3 "05 July 2017" "PCRE 8.41"
.SH NAME
PCRE - Perl-compatible regular expressions
.SH "PCRE JUST-IN-TIME COMPILER SUPPORT"
@@ -54,9 +54,12 @@ programs that need the best possible performance, there is also a "fast path"
API that is JIT-specific.
.P
If your program may sometimes be linked with versions of PCRE that are older
-than 8.20, but you want to use JIT when it is available, you can test
-the values of PCRE_MAJOR and PCRE_MINOR, or the existence of a JIT macro such
-as PCRE_CONFIG_JIT, for compile-time control of your code.
+than 8.20, but you want to use JIT when it is available, you can test the
+values of PCRE_MAJOR and PCRE_MINOR, or the existence of a JIT macro such as
+PCRE_CONFIG_JIT, for compile-time control of your code. Also beware that the
+\fBpcre_jit_exec()\fP function was not available at all before 8.32,
+and may not be available at all if PCRE isn't compiled with
+--enable-jit. See the "JIT FAST PATH API" section below for details.
.
.
.SH "SIMPLE USE OF JIT"
@@ -96,6 +99,19 @@ when you call \fBpcre_study()\fP:
PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE
PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE
.sp
+If using \fBpcre_jit_exec()\fP and supporting a pre-8.32 version of
+PCRE, you can insert:
+.sp
+ #if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32
+ pcre_jit_exec(...);
+ #else
+ pcre_exec(...)
+ #endif
+.sp
+but as described in the "JIT FAST PATH API" section below this assumes
+version 8.32 and later are compiled with --enable-jit, which may
+break.
+.sp
The JIT compiler generates different optimized code for each of the three
modes (normal, soft partial, hard partial). When \fBpcre_exec()\fP is called,
the appropriate code is run if it is available. Otherwise, the pattern is
@@ -404,6 +420,32 @@ fast path, and if invalid data is passed, the result is undefined.
.P
Bypassing the sanity checks and the \fBpcre_exec()\fP wrapping can give
speedups of more than 10%.
+.P
+Note that the \fBpcre_jit_exec()\fP function is not available in versions of
+PCRE before 8.32 (released in November 2012). If you need to support versions
+that old you must either use the slower \fBpcre_exec()\fP, or switch between
+the two codepaths by checking the values of PCRE_MAJOR and PCRE_MINOR.
+.P
+Due to an unfortunate implementation oversight, even in versions 8.32
+and later there will be no \fBpcre_jit_exec()\fP stub function defined
+when PCRE is compiled with --disable-jit, which is the default, and
+there's no way to detect whether PCRE was compiled with --enable-jit
+via a macro.
+.P
+If you need to support versions older than 8.32, or versions that may
+not build with --enable-jit, you must either use the slower
+\fBpcre_exec()\fP, or switch between the two codepaths by checking the
+values of PCRE_MAJOR and PCRE_MINOR.
+.P
+Switching between the two by checking the version assumes that all the
+versions being targeted are built with --enable-jit. To also support
+builds that may use --disable-jit either \fBpcre_exec()\fP must be
+used, or a compile-time check for JIT via \fBpcre_config()\fP (which
+assumes the runtime environment will be the same), or as the Git
+project decided to do, simply assume that \fBpcre_jit_exec()\fP is
+present in 8.32 or later unless a compile-time flag is provided, see
+the "grep: un-break building with PCRE >= 8.32 without --enable-jit"
+commit in git.git for an example of that.
.
.
.SH "SEE ALSO"
@@ -426,6 +468,6 @@ Cambridge CB2 3QH, England.
.rs
.sp
.nf
-Last updated: 17 March 2013
-Copyright (c) 1997-2013 University of Cambridge.
+Last updated: 05 July 2017
+Copyright (c) 1997-2017 University of Cambridge.
.fi
diff --git a/pcre/doc/pcretest.1 b/pcre/doc/pcretest.1
index 92640da8e1b..ea7457c03d0 100644
--- a/pcre/doc/pcretest.1
+++ b/pcre/doc/pcretest.1
@@ -1,4 +1,4 @@
-.TH PCRETEST 1 "09 February 2014" "PCRE 8.35"
+.TH PCRETEST 1 "23 February 2017" "PCRE 8.41"
.SH NAME
pcretest - a program for testing Perl-compatible regular expressions.
.SH SYNOPSIS
@@ -50,6 +50,10 @@ newline as data characters. However, in some Windows environments character 26
(hex 1A) causes an immediate end of file, and no further data is read. For
maximum portability, therefore, it is safest to use only ASCII characters in
\fBpcretest\fP input files.
+.P
+The input is processed using using C's string functions, so must not
+contain binary zeroes, even though in Unix-like environments, \fBfgets()\fP
+treats any bytes other than newline as data characters.
.
.
.SH "PCRE's 8-BIT, 16-BIT AND 32-BIT LIBRARIES"
@@ -1151,6 +1155,6 @@ Cambridge CB2 3QH, England.
.rs
.sp
.nf
-Last updated: 09 February 2014
-Copyright (c) 1997-2014 University of Cambridge.
+Last updated: 23 February 2017
+Copyright (c) 1997-2017 University of Cambridge.
.fi
diff --git a/pcre/doc/pcretest.txt b/pcre/doc/pcretest.txt
index 55de5024431..6d7305cfe82 100644
--- a/pcre/doc/pcretest.txt
+++ b/pcre/doc/pcretest.txt
@@ -39,6 +39,10 @@ INPUT DATA FORMAT
For maximum portability, therefore, it is safest to use only ASCII
characters in pcretest input files.
+ The input is processed using using C's string functions, so must not
+ contain binary zeroes, even though in Unix-like environments, fgets()
+ treats any bytes other than newline as data characters.
+
PCRE's 8-BIT, 16-BIT AND 32-BIT LIBRARIES
@@ -1083,5 +1087,5 @@ AUTHOR
REVISION
- Last updated: 09 February 2014
- Copyright (c) 1997-2014 University of Cambridge.
+ Last updated: 23 February 2017
+ Copyright (c) 1997-2017 University of Cambridge.
diff --git a/pcre/pcre.h.generic b/pcre/pcre.h.generic
index 206f314b87f..442c6bdb5fe 100644
--- a/pcre/pcre.h.generic
+++ b/pcre/pcre.h.generic
@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE_MAJOR 8
-#define PCRE_MINOR 40
+#define PCRE_MINOR 41
#define PCRE_PRERELEASE
-#define PCRE_DATE 2017-01-11
+#define PCRE_DATE 2017-07-05
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate
diff --git a/pcre/pcre_compile.c b/pcre/pcre_compile.c
index de92313e2f8..42f204cdfff 100644
--- a/pcre/pcre_compile.c
+++ b/pcre/pcre_compile.c
@@ -5739,6 +5739,21 @@ for (;; ptr++)
ptr = p - 1; /* Character before the next significant one. */
}
+ /* We also need to skip over (?# comments, which are not dependent on
+ extended mode. */
+
+ if (ptr[1] == CHAR_LEFT_PARENTHESIS && ptr[2] == CHAR_QUESTION_MARK &&
+ ptr[3] == CHAR_NUMBER_SIGN)
+ {
+ ptr += 4;
+ while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
+ if (*ptr == CHAR_NULL)
+ {
+ *errorcodeptr = ERR18;
+ goto FAILED;
+ }
+ }
+
/* If the next character is '+', we have a possessive quantifier. This
implies greediness, whatever the setting of the PCRE_UNGREEDY option.
If the next character is '?' this is a minimizing repeat, by default,
@@ -8210,7 +8225,6 @@ for (;; ptr++)
if (mclength == 1 || req_caseopt == 0)
{
- firstchar = mcbuffer[0] | req_caseopt;
firstchar = mcbuffer[0];
firstcharflags = req_caseopt;
diff --git a/pcre/pcre_dfa_exec.c b/pcre/pcre_dfa_exec.c
index 170ce6a0016..bc09ced3a7c 100644
--- a/pcre/pcre_dfa_exec.c
+++ b/pcre/pcre_dfa_exec.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language (but see
below for why this module is different).
Written by Philip Hazel
- Copyright (c) 1997-2014 University of Cambridge
+ Copyright (c) 1997-2017 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -2625,7 +2625,7 @@ for (;;)
if (isinclass)
{
int max = (int)GET2(ecode, 1 + IMM2_SIZE);
- if (*ecode == OP_CRPOSRANGE)
+ if (*ecode == OP_CRPOSRANGE && count >= (int)GET2(ecode, 1))
{
active_count--; /* Remove non-match possibility */
next_active_state--;
diff --git a/pcre/pcre_exec.c b/pcre/pcre_exec.c
index 24b23ca2864..1a9bdd546ee 100644
--- a/pcre/pcre_exec.c
+++ b/pcre/pcre_exec.c
@@ -669,7 +669,7 @@ if (ecode == NULL)
return match((PCRE_PUCHAR)&rdepth, NULL, NULL, 0, NULL, NULL, 1);
else
{
- int len = (char *)&rdepth - (char *)eptr;
+ int len = (int)((char *)&rdepth - (char *)eptr);
return (len > 0)? -len : len;
}
}
diff --git a/pcre/pcre_internal.h b/pcre/pcre_internal.h
index 2923b29f82d..97ff55d03b3 100644
--- a/pcre/pcre_internal.h
+++ b/pcre/pcre_internal.h
@@ -2772,6 +2772,9 @@ extern const pcre_uint8 PRIV(ucd_stage1)[];
extern const pcre_uint16 PRIV(ucd_stage2)[];
extern const pcre_uint32 PRIV(ucp_gentype)[];
extern const pcre_uint32 PRIV(ucp_gbtable)[];
+#ifdef COMPILE_PCRE32
+extern const ucd_record PRIV(dummy_ucd_record)[];
+#endif
#ifdef SUPPORT_JIT
extern const int PRIV(ucp_typerange)[];
#endif
@@ -2780,10 +2783,16 @@ extern const int PRIV(ucp_typerange)[];
/* UCD access macros */
#define UCD_BLOCK_SIZE 128
-#define GET_UCD(ch) (PRIV(ucd_records) + \
+#define REAL_GET_UCD(ch) (PRIV(ucd_records) + \
PRIV(ucd_stage2)[PRIV(ucd_stage1)[(int)(ch) / UCD_BLOCK_SIZE] * \
UCD_BLOCK_SIZE + (int)(ch) % UCD_BLOCK_SIZE])
+#ifdef COMPILE_PCRE32
+#define GET_UCD(ch) ((ch > 0x10ffff)? PRIV(dummy_ucd_record) : REAL_GET_UCD(ch))
+#else
+#define GET_UCD(ch) REAL_GET_UCD(ch)
+#endif
+
#define UCD_CHARTYPE(ch) GET_UCD(ch)->chartype
#define UCD_SCRIPT(ch) GET_UCD(ch)->script
#define UCD_CATEGORY(ch) PRIV(ucp_gentype)[UCD_CHARTYPE(ch)]
diff --git a/pcre/pcre_jit_compile.c b/pcre/pcre_jit_compile.c
index 46ce6c65d54..249edbe8e7f 100644
--- a/pcre/pcre_jit_compile.c
+++ b/pcre/pcre_jit_compile.c
@@ -487,7 +487,7 @@ typedef struct compare_context {
#undef CMP
/* Used for accessing the elements of the stack. */
-#define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_sw))
+#define STACK(i) ((i) * (int)sizeof(sljit_sw))
#define TMP1 SLJIT_R0
#define TMP2 SLJIT_R2
@@ -552,13 +552,15 @@ the start pointers when the end of the capturing group has not yet reached. */
sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
#define CMPTO(type, src1, src1w, src2, src2w, label) \
sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
-#define OP_FLAGS(op, dst, dstw, src, srcw, type) \
- sljit_emit_op_flags(compiler, (op), (dst), (dstw), (src), (srcw), (type))
+#define OP_FLAGS(op, dst, dstw, type) \
+ sljit_emit_op_flags(compiler, (op), (dst), (dstw), (type))
#define GET_LOCAL_BASE(dst, dstw, offset) \
sljit_get_local_base(compiler, (dst), (dstw), (offset))
#define READ_CHAR_MAX 0x7fffffff
+#define INVALID_UTF_CHAR 888
+
static pcre_uchar *bracketend(pcre_uchar *cc)
{
SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
@@ -784,7 +786,7 @@ switch(*cc)
default:
/* All opcodes are supported now! */
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return NULL;
}
}
@@ -1660,9 +1662,9 @@ while (cc < ccend)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
setsom_found = TRUE;
}
cc += 1;
@@ -1676,9 +1678,9 @@ while (cc < ccend)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
setmark_found = TRUE;
}
cc += 1 + 2 + cc[1];
@@ -1689,27 +1691,27 @@ while (cc < ccend)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
setsom_found = TRUE;
}
if (common->mark_ptr != 0 && !setmark_found)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
setmark_found = TRUE;
}
if (common->capture_last_ptr != 0 && !capture_last_found)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
capture_last_found = TRUE;
}
cc += 1 + LINK_SIZE;
@@ -1723,20 +1725,20 @@ while (cc < ccend)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
capture_last_found = TRUE;
}
offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
- stackpos += (int)sizeof(sljit_sw);
+ stackpos -= (int)sizeof(sljit_sw);
cc += 1 + LINK_SIZE + IMM2_SIZE;
break;
@@ -1887,18 +1889,17 @@ BOOL tmp1empty = TRUE;
BOOL tmp2empty = TRUE;
pcre_uchar *alternative;
enum {
- start,
loop,
end
} status;
-status = save ? start : loop;
-stackptr = STACK(stackptr - 2);
+status = loop;
+stackptr = STACK(stackptr);
stacktop = STACK(stacktop - 1);
if (!save)
{
- stackptr += (needs_control_head ? 2 : 1) * sizeof(sljit_sw);
+ stacktop -= (needs_control_head ? 2 : 1) * sizeof(sljit_sw);
if (stackptr < stacktop)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
@@ -1914,196 +1915,186 @@ if (!save)
/* The tmp1next must be TRUE in either way. */
}
+SLJIT_ASSERT(common->recursive_head_ptr != 0);
+
do
{
count = 0;
- switch(status)
+ if (cc >= ccend)
{
- case start:
- SLJIT_ASSERT(save && common->recursive_head_ptr != 0);
+ if (!save)
+ break;
+
count = 1;
srcw[0] = common->recursive_head_ptr;
if (needs_control_head)
{
SLJIT_ASSERT(common->control_head_ptr != 0);
count = 2;
- srcw[1] = common->control_head_ptr;
+ srcw[0] = common->control_head_ptr;
+ srcw[1] = common->recursive_head_ptr;
}
- status = loop;
+ status = end;
+ }
+ else switch(*cc)
+ {
+ case OP_KET:
+ if (PRIVATE_DATA(cc) != 0)
+ {
+ count = 1;
+ srcw[0] = PRIVATE_DATA(cc);
+ SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
+ cc += PRIVATE_DATA(cc + 1);
+ }
+ cc += 1 + LINK_SIZE;
break;
- case loop:
- if (cc >= ccend)
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_BRAPOS:
+ case OP_SBRA:
+ case OP_SBRAPOS:
+ case OP_SCOND:
+ count = 1;
+ srcw[0] = PRIVATE_DATA(cc);
+ SLJIT_ASSERT(srcw[0] != 0);
+ cc += 1 + LINK_SIZE;
+ break;
+
+ case OP_CBRA:
+ case OP_SCBRA:
+ if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
{
- status = end;
- break;
+ count = 1;
+ srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
}
+ cc += 1 + LINK_SIZE + IMM2_SIZE;
+ break;
- switch(*cc)
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
+ SLJIT_ASSERT(srcw[0] != 0 && srcw[1] != 0);
+ cc += 1 + LINK_SIZE + IMM2_SIZE;
+ break;
+
+ case OP_COND:
+ /* Might be a hidden SCOND. */
+ alternative = cc + GET(cc, 1);
+ if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
{
- case OP_KET:
- if (PRIVATE_DATA(cc) != 0)
- {
- count = 1;
- srcw[0] = PRIVATE_DATA(cc);
- SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
- cc += PRIVATE_DATA(cc + 1);
- }
- cc += 1 + LINK_SIZE;
- break;
-
- case OP_ASSERT:
- case OP_ASSERT_NOT:
- case OP_ASSERTBACK:
- case OP_ASSERTBACK_NOT:
- case OP_ONCE:
- case OP_ONCE_NC:
- case OP_BRAPOS:
- case OP_SBRA:
- case OP_SBRAPOS:
- case OP_SCOND:
count = 1;
srcw[0] = PRIVATE_DATA(cc);
SLJIT_ASSERT(srcw[0] != 0);
- cc += 1 + LINK_SIZE;
- break;
-
- case OP_CBRA:
- case OP_SCBRA:
- if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
- {
- count = 1;
- srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
- }
- cc += 1 + LINK_SIZE + IMM2_SIZE;
- break;
-
- case OP_CBRAPOS:
- case OP_SCBRAPOS:
- count = 2;
- srcw[0] = PRIVATE_DATA(cc);
- srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
- SLJIT_ASSERT(srcw[0] != 0 && srcw[1] != 0);
- cc += 1 + LINK_SIZE + IMM2_SIZE;
- break;
-
- case OP_COND:
- /* Might be a hidden SCOND. */
- alternative = cc + GET(cc, 1);
- if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
- {
- count = 1;
- srcw[0] = PRIVATE_DATA(cc);
- SLJIT_ASSERT(srcw[0] != 0);
- }
- cc += 1 + LINK_SIZE;
- break;
-
- CASE_ITERATOR_PRIVATE_DATA_1
- if (PRIVATE_DATA(cc))
- {
- count = 1;
- srcw[0] = PRIVATE_DATA(cc);
- }
- cc += 2;
-#ifdef SUPPORT_UTF
- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
-#endif
- break;
-
- CASE_ITERATOR_PRIVATE_DATA_2A
- if (PRIVATE_DATA(cc))
- {
- count = 2;
- srcw[0] = PRIVATE_DATA(cc);
- srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
- }
- cc += 2;
-#ifdef SUPPORT_UTF
- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
-#endif
- break;
-
- CASE_ITERATOR_PRIVATE_DATA_2B
- if (PRIVATE_DATA(cc))
- {
- count = 2;
- srcw[0] = PRIVATE_DATA(cc);
- srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
- }
- cc += 2 + IMM2_SIZE;
-#ifdef SUPPORT_UTF
- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
-#endif
- break;
-
- CASE_ITERATOR_TYPE_PRIVATE_DATA_1
- if (PRIVATE_DATA(cc))
- {
- count = 1;
- srcw[0] = PRIVATE_DATA(cc);
- }
- cc += 1;
- break;
-
- CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
- if (PRIVATE_DATA(cc))
- {
- count = 2;
- srcw[0] = PRIVATE_DATA(cc);
- srcw[1] = srcw[0] + sizeof(sljit_sw);
- }
- cc += 1;
- break;
-
- CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
- if (PRIVATE_DATA(cc))
- {
- count = 2;
- srcw[0] = PRIVATE_DATA(cc);
- srcw[1] = srcw[0] + sizeof(sljit_sw);
- }
- cc += 1 + IMM2_SIZE;
- break;
-
- case OP_CLASS:
- case OP_NCLASS:
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
- case OP_XCLASS:
- size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar);
-#else
- size = 1 + 32 / (int)sizeof(pcre_uchar);
-#endif
- if (PRIVATE_DATA(cc))
- switch(get_class_iterator_size(cc + size))
- {
- case 1:
- count = 1;
- srcw[0] = PRIVATE_DATA(cc);
- break;
-
- case 2:
- count = 2;
- srcw[0] = PRIVATE_DATA(cc);
- srcw[1] = srcw[0] + sizeof(sljit_sw);
- break;
-
- default:
- SLJIT_ASSERT_STOP();
- break;
- }
- cc += size;
- break;
-
- default:
- cc = next_opcode(common, cc);
- SLJIT_ASSERT(cc != NULL);
- break;
}
+ cc += 1 + LINK_SIZE;
break;
- case end:
- SLJIT_ASSERT_STOP();
+ CASE_ITERATOR_PRIVATE_DATA_1
+ if (PRIVATE_DATA(cc))
+ {
+ count = 1;
+ srcw[0] = PRIVATE_DATA(cc);
+ }
+ cc += 2;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ CASE_ITERATOR_PRIVATE_DATA_2A
+ if (PRIVATE_DATA(cc))
+ {
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
+ }
+ cc += 2;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ CASE_ITERATOR_PRIVATE_DATA_2B
+ if (PRIVATE_DATA(cc))
+ {
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
+ }
+ cc += 2 + IMM2_SIZE;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_1
+ if (PRIVATE_DATA(cc))
+ {
+ count = 1;
+ srcw[0] = PRIVATE_DATA(cc);
+ }
+ cc += 1;
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
+ if (PRIVATE_DATA(cc))
+ {
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = srcw[0] + sizeof(sljit_sw);
+ }
+ cc += 1;
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
+ if (PRIVATE_DATA(cc))
+ {
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = srcw[0] + sizeof(sljit_sw);
+ }
+ cc += 1 + IMM2_SIZE;
+ break;
+
+ case OP_CLASS:
+ case OP_NCLASS:
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar);
+#else
+ size = 1 + 32 / (int)sizeof(pcre_uchar);
+#endif
+ if (PRIVATE_DATA(cc))
+ switch(get_class_iterator_size(cc + size))
+ {
+ case 1:
+ count = 1;
+ srcw[0] = PRIVATE_DATA(cc);
+ break;
+
+ case 2:
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = srcw[0] + sizeof(sljit_sw);
+ break;
+
+ default:
+ SLJIT_UNREACHABLE();
+ break;
+ }
+ cc += size;
+ break;
+
+ default:
+ cc = next_opcode(common, cc);
+ SLJIT_ASSERT(cc != NULL);
break;
}
@@ -2312,7 +2303,7 @@ static SLJIT_INLINE void count_match(compiler_common *common)
{
DEFINE_COMPILER;
-OP2(SLJIT_SUB | SLJIT_SET_E, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);
+OP2(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);
add_jump(compiler, &common->calllimit, JUMP(SLJIT_ZERO));
}
@@ -2322,7 +2313,7 @@ static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
DEFINE_COMPILER;
SLJIT_ASSERT(size > 0);
-OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
+OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
#ifdef DESTROY_REGISTERS
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
@@ -2330,7 +2321,7 @@ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP1, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0);
#endif
-add_stub(common, CMP(SLJIT_GREATER, STACK_TOP, 0, STACK_LIMIT, 0));
+add_stub(common, CMP(SLJIT_LESS, STACK_TOP, 0, STACK_LIMIT, 0));
}
static SLJIT_INLINE void free_stack(compiler_common *common, int size)
@@ -2338,7 +2329,7 @@ static SLJIT_INLINE void free_stack(compiler_common *common, int size)
DEFINE_COMPILER;
SLJIT_ASSERT(size > 0);
-OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
+OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
}
static sljit_uw * allocate_read_only_data(compiler_common *common, sljit_uw size)
@@ -2396,7 +2387,7 @@ else
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
loop = LABEL();
OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R0, 0);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, loop);
}
}
@@ -2434,7 +2425,7 @@ else
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
loop = LABEL();
OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
- OP2(SLJIT_SUB | SLJIT_SET_E, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, loop);
}
@@ -2452,22 +2443,22 @@ static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, const pcre_uchar *s
{
while (current != NULL)
{
- switch (current[-2])
+ switch (current[1])
{
case type_then_trap:
break;
case type_mark:
- if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0)
- return current[-4];
+ if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[2]) == 0)
+ return current[3];
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
- SLJIT_ASSERT(current > (sljit_sw*)current[-1]);
- current = (sljit_sw*)current[-1];
+ SLJIT_ASSERT(current[0] == 0 || current < (sljit_sw*)current[0]);
+ current = (sljit_sw*)current[0];
}
return -1;
}
@@ -2501,7 +2492,7 @@ OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));
OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);
#endif
OP1(SLJIT_MOVU_S32, SLJIT_MEM1(SLJIT_R2), sizeof(int), SLJIT_S1, 0);
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, loop);
JUMPHERE(early_quit);
@@ -3106,8 +3097,8 @@ if (common->utf)
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
/* Skip low surrogate if necessary. */
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
return;
@@ -3126,6 +3117,7 @@ struct sljit_jump *jump;
if (nltype == NLTYPE_ANY)
{
add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
+ sljit_set_current_flags(compiler, SLJIT_SET_Z);
add_jump(compiler, backtracks, JUMP(jumpifmatch ? SLJIT_NOT_ZERO : SLJIT_ZERO));
}
else if (nltype == NLTYPE_ANYCRLF)
@@ -3167,7 +3159,7 @@ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
/* Searching for the first zero. */
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
jump = JUMP(SLJIT_NOT_ZERO);
/* Two byte sequence. */
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
@@ -3181,7 +3173,7 @@ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);
jump = JUMP(SLJIT_NOT_ZERO);
/* Three byte sequence. */
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
@@ -3215,15 +3207,15 @@ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
/* Searching for the first zero. */
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
jump = JUMP(SLJIT_NOT_ZERO);
/* Two byte sequence. */
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
JUMPHERE(jump);
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_NOT_ZERO);
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO);
/* This code runs only in 8 bit mode. No need to shift the value. */
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
@@ -3246,7 +3238,7 @@ struct sljit_jump *compare;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
jump = JUMP(SLJIT_NOT_ZERO);
/* Two byte sequence. */
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
@@ -3287,10 +3279,30 @@ static void do_getucd(compiler_common *common)
/* Search the UCD record for the character comes in TMP1.
Returns chartype in TMP1 and UCD offset in TMP2. */
DEFINE_COMPILER;
+#ifdef COMPILE_PCRE32
+struct sljit_jump *jump;
+#endif
+
+#if defined SLJIT_DEBUG && SLJIT_DEBUG
+/* dummy_ucd_record */
+const ucd_record *record = GET_UCD(INVALID_UTF_CHAR);
+SLJIT_ASSERT(record->script == ucp_Common && record->chartype == ucp_Cn && record->gbprop == ucp_gbOther);
+SLJIT_ASSERT(record->caseset == 0 && record->other_case == 0);
+#endif
SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+#ifdef COMPILE_PCRE32
+if (!common->utf)
+ {
+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10ffff + 1);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+ JUMPHERE(jump);
+ }
+#endif
+
OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
@@ -3365,8 +3377,8 @@ if (newlinecheck)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
#endif
@@ -3403,8 +3415,8 @@ if (common->utf)
{
singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
JUMPHERE(singlechar);
@@ -3853,7 +3865,7 @@ while (TRUE)
}
}
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
static sljit_s32 character_to_int32(pcre_uchar chr)
{
@@ -4019,6 +4031,7 @@ instruction[0] = 0x0f;
instruction[1] = 0xbc;
instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
sljit_emit_op_custom(compiler, instruction, 3);
+sljit_set_current_flags(compiler, SLJIT_SET_Z);
nomatch = JUMP(SLJIT_ZERO);
@@ -4119,6 +4132,7 @@ instruction[0] = 0x0f;
instruction[1] = 0xbc;
instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
sljit_emit_op_custom(compiler, instruction, 3);
+sljit_set_current_flags(compiler, SLJIT_SET_Z);
JUMPTO(SLJIT_ZERO, start);
@@ -4155,18 +4169,8 @@ if (has_match_end)
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
OP2(SLJIT_ADD, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, SLJIT_IMM, IN_UCHARS(offset + 1));
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
- if (sljit_x86_is_cmov_available())
- {
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_END, 0, TMP3, 0);
- sljit_x86_emit_cmov(compiler, SLJIT_GREATER, STR_END, TMP3, 0);
- }
-#endif
- {
- quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP3, 0);
- OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
- JUMPHERE(quit);
- }
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP3, 0);
+ sljit_emit_cmov(compiler, SLJIT_GREATER, STR_END, TMP3, 0);
}
#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
@@ -4174,11 +4178,11 @@ if (common->utf && offset > 0)
utf_start = LABEL();
#endif
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
/* SSE2 accelerated first character search. */
-if (sljit_x86_is_sse2_available())
+if (sljit_has_cpu_feature(SLJIT_HAS_SSE2))
{
fast_forward_first_char2_sse2(common, char1, char2);
@@ -4213,16 +4217,16 @@ if (sljit_x86_is_sse2_available())
if (offset > 0)
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
}
- else if (sljit_x86_is_cmov_available())
- {
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
- sljit_x86_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, has_match_end ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_match_end ? common->match_end_ptr : 0);
- }
else
{
- quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
- OP1(SLJIT_MOV, STR_PTR, 0, has_match_end ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_match_end ? common->match_end_ptr : 0);
- JUMPHERE(quit);
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ if (has_match_end)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
+ sljit_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, TMP1, 0);
+ }
+ else
+ sljit_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, STR_END, 0);
}
if (has_match_end)
@@ -4249,10 +4253,10 @@ else
}
else
{
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char1);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char2);
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char1);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char2);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
found = JUMP(SLJIT_NOT_ZERO);
}
}
@@ -4571,8 +4575,8 @@ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER_EQUAL);
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);
#endif
@@ -4616,8 +4620,8 @@ if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
JUMPHERE(foundcr);
notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
#endif
@@ -4670,7 +4674,7 @@ if (!check_class_ranges(common, start_bits, (start_bits[31] & 0x80) != 0, TRUE,
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits);
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
- OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
found = JUMP(SLJIT_NOT_ZERO);
}
@@ -4692,8 +4696,8 @@ if (common->utf)
{
CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start);
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
}
@@ -4780,31 +4784,31 @@ struct sljit_jump *jump;
struct sljit_label *mainloop;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
-OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0);
-GET_LOCAL_BASE(TMP3, 0, 0);
+OP1(SLJIT_MOV, TMP3, 0, STACK_TOP, 0);
+GET_LOCAL_BASE(TMP1, 0, 0);
/* Drop frames until we reach STACK_TOP. */
mainloop = LABEL();
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);
-OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0);
-jump = JUMP(SLJIT_SIG_LESS_EQUAL);
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), -sizeof(sljit_sw));
+jump = CMP(SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0);
-OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0);
-OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw));
-OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_sw));
-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -2 * sizeof(sljit_sw));
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(STACK_TOP), -3 * sizeof(sljit_sw));
+OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));
JUMPTO(SLJIT_JUMP, mainloop);
JUMPHERE(jump);
-jump = JUMP(SLJIT_SIG_LESS);
-/* End of dropping frames. */
+jump = CMP(SLJIT_NOT_ZERO /* SIG_LESS */, TMP2, 0, SLJIT_IMM, 0);
+/* End of reverting values. */
+OP1(SLJIT_MOV, STACK_TOP, 0, TMP3, 0);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
JUMPHERE(jump);
OP1(SLJIT_NEG, TMP2, 0, TMP2, 0);
-OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0);
-OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw));
-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -2 * sizeof(sljit_sw));
+OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));
JUMPTO(SLJIT_JUMP, mainloop);
}
@@ -4837,11 +4841,11 @@ if (common->use_ucp)
jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
JUMPHERE(jump);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0);
}
@@ -4881,11 +4885,11 @@ if (common->use_ucp)
jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
JUMPHERE(jump);
}
else
@@ -4913,7 +4917,7 @@ else
}
set_jumps(skipread_list, LABEL());
-OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
+OP2(SLJIT_XOR | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
}
@@ -5064,7 +5068,7 @@ switch(length)
return TRUE;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return FALSE;
}
}
@@ -5077,22 +5081,22 @@ DEFINE_COMPILER;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
-OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
+OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
#ifdef COMPILE_PCRE8
if (common->utf)
{
#endif
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
#ifdef COMPILE_PCRE8
}
#endif
#endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
-OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
@@ -5103,34 +5107,34 @@ DEFINE_COMPILER;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
-OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
#ifdef COMPILE_PCRE8
if (common->utf)
{
#endif
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
#ifdef COMPILE_PCRE8
}
#endif
#endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
-OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
@@ -5143,22 +5147,22 @@ DEFINE_COMPILER;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
-OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
+OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
#ifdef COMPILE_PCRE8
if (common->utf)
{
#endif
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
#ifdef COMPILE_PCRE8
}
#endif
#endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
-OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
@@ -5183,7 +5187,7 @@ label = LABEL();
OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
-OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
+OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
JUMPTO(SLJIT_NOT_ZERO, label);
JUMPHERE(jump);
@@ -5227,7 +5231,7 @@ OP1(SLJIT_MOV_U8, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
JUMPHERE(jump);
#endif
jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
-OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
+OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
JUMPTO(SLJIT_NOT_ZERO, label);
JUMPHERE(jump);
@@ -5394,7 +5398,7 @@ do
#endif
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
context->ucharptr = 0;
@@ -5568,7 +5572,7 @@ while (*cc != XCL_END)
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
cc += 2;
@@ -5592,7 +5596,7 @@ if ((cc[-1] & XCL_HASPROP) == 0)
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
- OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
add_jump(compiler, &found, JUMP(SLJIT_NOT_ZERO));
}
@@ -5625,7 +5629,7 @@ else if ((cc[-1] & XCL_MAP) != 0)
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
- OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO));
#ifdef COMPILE_PCRE8
@@ -5644,6 +5648,15 @@ if (needstype || needsscript)
if (needschar && !charsaved)
OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
+#ifdef COMPILE_PCRE32
+ if (!common->utf)
+ {
+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10ffff + 1);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+ JUMPHERE(jump);
+ }
+#endif
+
OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
@@ -5735,14 +5748,14 @@ while (*cc != XCL_END)
if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
{
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
- OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
numberofcmps++;
}
else if (numberofcmps > 0)
{
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
numberofcmps = 0;
}
@@ -5761,14 +5774,14 @@ while (*cc != XCL_END)
if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
{
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
- OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
numberofcmps++;
}
else if (numberofcmps > 0)
{
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
numberofcmps = 0;
}
@@ -5793,12 +5806,12 @@ while (*cc != XCL_END)
break;
case PT_LAMP:
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
@@ -5820,33 +5833,33 @@ while (*cc != XCL_END)
case PT_SPACE:
case PT_PXSPACE:
SET_CHAR_OFFSET(9);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
SET_TYPE_OFFSET(ucp_Zl);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
case PT_WORD:
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset));
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset));
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
/* Fall through. */
case PT_ALNUM:
SET_TYPE_OFFSET(ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
- OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, (*cc == PT_ALNUM) ? SLJIT_UNUSED : TMP2, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+ OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
SET_TYPE_OFFSET(ucp_Nd);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
@@ -5868,8 +5881,8 @@ while (*cc != XCL_END)
OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);
OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
}
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
other_cases += 2;
}
else if (is_powerof2(other_cases[2] ^ other_cases[1]))
@@ -5881,63 +5894,63 @@ while (*cc != XCL_END)
OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);
OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
}
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset));
- OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset));
+ OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);
other_cases += 3;
}
else
{
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
}
while (*other_cases != NOTACHAR)
{
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
- OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
+ OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);
}
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
case PT_UCNC:
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
SET_CHAR_OFFSET(0xa0);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
SET_CHAR_OFFSET(0);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0);
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_GREATER_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_GREATER_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
case PT_PXGRAPH:
/* C and Z groups are the farthest two groups. */
SET_TYPE_OFFSET(ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER);
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER);
jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);
/* In case of ucp_Cf, we overwrite the result. */
SET_CHAR_OFFSET(0x2066);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066);
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
JUMPHERE(jump);
jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);
@@ -5946,21 +5959,21 @@ while (*cc != XCL_END)
case PT_PXPRINT:
/* C and Z groups are the farthest two groups. */
SET_TYPE_OFFSET(ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER);
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll);
- OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_NOT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll);
+ OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_NOT_EQUAL);
jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);
/* In case of ucp_Cf, we overwrite the result. */
SET_CHAR_OFFSET(0x2066);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
- OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
JUMPHERE(jump);
jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);
@@ -5968,21 +5981,21 @@ while (*cc != XCL_END)
case PT_PXPUNCT:
SET_TYPE_OFFSET(ucp_Sc);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
SET_CHAR_OFFSET(0);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f);
- OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f);
+ OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_LESS_EQUAL);
SET_TYPE_OFFSET(ucp_Pc);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc);
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
cc += 2;
@@ -6028,6 +6041,7 @@ switch(type)
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
+ sljit_set_current_flags(compiler, SLJIT_SET_Z);
add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_NOT_ZERO : SLJIT_ZERO));
return cc;
@@ -6043,10 +6057,10 @@ switch(type)
else
{
jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0);
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
- OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_NOT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_EQUAL);
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL));
check_partial(common, TRUE);
add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
@@ -6068,9 +6082,9 @@ switch(type)
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
- OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
+ OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
jump[2] = JUMP(SLJIT_GREATER);
- add_jump(compiler, backtracks, JUMP(SLJIT_LESS));
+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL) /* LESS */);
/* Equal. */
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
jump[3] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
@@ -6089,6 +6103,7 @@ switch(type)
read_char_range(common, common->nlmin, common->nlmax, TRUE);
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
+ sljit_set_current_flags(compiler, SLJIT_SET_Z);
add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
}
@@ -6204,7 +6219,7 @@ switch(type)
label = LABEL();
add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP3, 0));
skip_char_back(common);
- OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, label);
}
else
@@ -6217,7 +6232,7 @@ switch(type)
check_start_used_ptr(common);
return cc + LINK_SIZE;
}
-SLJIT_ASSERT_STOP();
+SLJIT_UNREACHABLE();
return cc;
}
@@ -6250,7 +6265,7 @@ switch(type)
#endif
read_char8_type(common, type == OP_NOT_DIGIT);
/* Flip the starting bit in the negative case. */
- OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_ZERO : SLJIT_NOT_ZERO));
return cc;
@@ -6264,7 +6279,7 @@ switch(type)
else
#endif
read_char8_type(common, type == OP_NOT_WHITESPACE);
- OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_ZERO : SLJIT_NOT_ZERO));
return cc;
@@ -6278,7 +6293,7 @@ switch(type)
else
#endif
read_char8_type(common, type == OP_NOT_WORDCHAR);
- OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO));
return cc;
@@ -6320,8 +6335,8 @@ switch(type)
#elif defined COMPILE_PCRE16
jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
#endif
@@ -6383,6 +6398,7 @@ switch(type)
detect_partial_match(common, backtracks);
read_char_range(common, 0x9, 0x3000, type == OP_NOT_HSPACE);
add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
+ sljit_set_current_flags(compiler, SLJIT_SET_Z);
add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));
return cc;
@@ -6392,6 +6408,7 @@ switch(type)
detect_partial_match(common, backtracks);
read_char_range(common, 0xa, 0x2029, type == OP_NOT_VSPACE);
add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
+ sljit_set_current_flags(compiler, SLJIT_SET_Z);
add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));
return cc;
@@ -6418,7 +6435,7 @@ switch(type)
OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(STACK_TOP), (sljit_sw)PRIV(ucp_gbtable));
OP1(SLJIT_MOV, STACK_TOP, 0, TMP2, 0);
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
- OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
JUMPTO(SLJIT_NOT_ZERO, label);
OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
@@ -6587,7 +6604,7 @@ switch(type)
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
- OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
@@ -6604,7 +6621,7 @@ switch(type)
return cc + GET(cc, 0) - 1;
#endif
}
-SLJIT_ASSERT_STOP();
+SLJIT_UNREACHABLE();
return cc;
}
@@ -6790,9 +6807,9 @@ else
#endif /* SUPPORT_UTF && SUPPORT_UCP */
{
if (ref)
- OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);
else
- OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
if (withchecks)
jump = JUMP(SLJIT_ZERO);
@@ -6883,7 +6900,7 @@ switch(type)
cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE;
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
@@ -6897,7 +6914,7 @@ if (!minimize)
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
/* Temporary release of STR_PTR. */
- OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
/* Handles both invalid and empty cases. Since the minimum repeat,
is zero the invalid case is basically the same as an empty case. */
if (ref)
@@ -6910,7 +6927,7 @@ if (!minimize)
zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
}
/* Restore if not zero length. */
- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
}
else
{
@@ -7157,7 +7174,7 @@ return (*PUBL(callout))(callout_block);
(((int)sizeof(PUBL(callout_block)) + 7) & ~7)
#define CALLOUT_ARG_OFFSET(arg) \
- (-CALLOUT_ARG_SIZE + SLJIT_OFFSETOF(PUBL(callout_block), arg))
+ SLJIT_OFFSETOF(PUBL(callout_block), arg)
static SLJIT_INLINE pcre_uchar *compile_callout_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
{
@@ -7187,7 +7204,8 @@ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_pt
/* Needed to save important temporary registers. */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
-OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_TOP, 0, SLJIT_IMM, CALLOUT_ARG_SIZE);
+/* SLJIT_R0 = arguments */
+OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0);
GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START);
sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout));
OP1(SLJIT_MOV_S32, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0);
@@ -7195,12 +7213,12 @@ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
free_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw));
/* Check return value. */
-OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
+OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER));
if (common->forced_quit_label == NULL)
- add_jump(compiler, &common->forced_quit, JUMP(SLJIT_SIG_LESS));
+ add_jump(compiler, &common->forced_quit, JUMP(SLJIT_NOT_EQUAL) /* SIG_LESS */);
else
- JUMPTO(SLJIT_SIG_LESS, common->forced_quit_label);
+ JUMPTO(SLJIT_NOT_EQUAL /* SIG_LESS */, common->forced_quit_label);
return cc + 2 + 2 * LINK_SIZE;
}
@@ -7321,7 +7339,7 @@ else
allocate_stack(common, framesize + extrasize);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
- OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
+ OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);
if (needs_control_head)
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
@@ -7392,22 +7410,22 @@ while (1)
free_stack(common, extrasize);
if (needs_control_head)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));
}
else
{
if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional)
{
/* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
- OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
if (needs_control_head)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));
}
else
{
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
if (needs_control_head)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 2));
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
}
}
@@ -7418,25 +7436,25 @@ while (1)
if (conditional)
{
if (extrasize > 0)
- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0);
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? STACK(-2) : STACK(-1));
}
else if (bra == OP_BRAZERO)
{
if (framesize < 0)
- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize));
else
{
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw));
- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + extrasize - 1) * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1));
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - extrasize));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);
}
- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
}
else if (framesize >= 0)
{
/* For OP_BRA and OP_BRAMINZERO. */
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1));
}
}
add_jump(compiler, found, JUMP(SLJIT_JUMP));
@@ -7480,12 +7498,12 @@ if (common->positive_assert_quit != NULL)
set_jumps(common->positive_assert_quit, LABEL());
SLJIT_ASSERT(framesize != no_stack);
if (framesize < 0)
- OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));
else
{
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
}
JUMPHERE(jump);
}
@@ -7534,18 +7552,18 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
{
/* We know that STR_PTR was stored on the top of the stack. */
if (extrasize > 0)
- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize));
/* Keep the STR_PTR on the top of the stack. */
if (bra == OP_BRAZERO)
{
- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
if (extrasize == 2)
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
}
else if (bra == OP_BRAMINZERO)
{
- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
}
}
@@ -7554,13 +7572,13 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
if (bra == OP_BRA)
{
/* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
- OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 2) * sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize + 1));
}
else
{
/* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
- OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw));
if (extrasize == 2)
{
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
@@ -7588,7 +7606,7 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
{
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1));
}
set_jumps(backtrack->common.topbacktracks, LABEL());
}
@@ -7675,23 +7693,23 @@ if (framesize < 0)
}
if (needs_control_head)
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? sizeof(sljit_sw) : 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? STACK(-2) : STACK(-1));
/* TMP2 which is set here used by OP_KETRMAX below. */
if (ket == OP_KETRMAX)
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-1));
else if (ket == OP_KETRMIN)
{
/* Move the STR_PTR to the private_data_ptr. */
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));
}
}
else
{
stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1;
- OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw));
if (needs_control_head)
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-1));
if (ket == OP_KETRMAX)
{
@@ -7927,7 +7945,7 @@ if (bra == OP_BRAMINZERO)
{
/* Except when the whole stack frame must be saved. */
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
- braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw));
+ braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-BACKTRACK_AS(bracket_backtrack)->u.framesize - 2));
}
JUMPHERE(skip);
}
@@ -8000,7 +8018,7 @@ if (opcode == OP_ONCE)
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame)
- OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw));
+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw));
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0);
}
else if (ket == OP_KETRMAX || has_alternatives)
@@ -8018,7 +8036,7 @@ if (opcode == OP_ONCE)
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
- OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
+ OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
stacksize = needs_control_head ? 1 : 0;
if (ket != OP_KET || has_alternatives)
@@ -8090,13 +8108,13 @@ if (opcode == OP_COND || opcode == OP_SCOND)
slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;
OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
- OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
slot += common->name_entry_size;
i--;
while (i-- > 0)
{
OP2(SLJIT_SUB, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
- OP2(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, STR_PTR, 0);
+ OP2(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, STR_PTR, 0);
slot += common->name_entry_size;
}
OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
@@ -8111,7 +8129,7 @@ if (opcode == OP_COND || opcode == OP_SCOND)
if (*matchingpath == OP_FAIL)
stacksize = 0;
- if (*matchingpath == OP_RREF)
+ else if (*matchingpath == OP_RREF)
{
stacksize = GET2(matchingpath, 1);
if (common->currententry == NULL)
@@ -8244,7 +8262,7 @@ if (ket == OP_KETRMAX)
{
if (has_alternatives)
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, rmax_label);
/* Drop STR_PTR for greedy plus quantifier. */
if (opcode != OP_ONCE)
@@ -8274,7 +8292,7 @@ if (ket == OP_KETRMAX)
if (repeat_type == OP_EXACT)
{
count_match(common);
- OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, rmax_label);
}
else if (repeat_type == OP_UPTO)
@@ -8374,7 +8392,7 @@ switch(opcode)
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
@@ -8452,7 +8470,7 @@ else
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
if (needs_control_head)
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
- OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1));
+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
stack = 0;
if (!zero)
@@ -8524,7 +8542,7 @@ while (*cc != OP_KETRPOS)
{
if (offset != 0)
{
- OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw));
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0);
@@ -8535,10 +8553,10 @@ while (*cc != OP_KETRPOS)
else
{
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
- OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
if (opcode == OP_SBRAPOS)
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw));
- OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw), STR_PTR, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2));
+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), STACK(-framesize - 2), STR_PTR, 0);
}
/* Even if the match is empty, we need to reset the control head. */
@@ -8584,7 +8602,7 @@ while (*cc != OP_KETRPOS)
else
{
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2));
}
}
@@ -8601,7 +8619,7 @@ if (!zero)
if (framesize < 0)
add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));
else /* TMP2 is set to [private_data_ptr] above. */
- add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_sw), SLJIT_IMM, 0));
+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), STACK(-stacksize), SLJIT_IMM, 0));
}
/* None of them matched. */
@@ -8824,7 +8842,7 @@ if (exact > 1)
OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact);
label = LABEL();
compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);
- OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, label);
}
else
@@ -8832,7 +8850,7 @@ if (exact > 1)
OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact);
label = LABEL();
compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE);
- OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, label);
}
}
@@ -8862,7 +8880,7 @@ switch(opcode)
if (opcode == OP_UPTO)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0);
- OP2(SLJIT_SUB | SLJIT_SET_E, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
jump = JUMP(SLJIT_ZERO);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0);
}
@@ -8924,7 +8942,7 @@ switch(opcode)
label = LABEL();
if (opcode == OP_UPTO)
{
- OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO));
}
compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);
@@ -8944,7 +8962,7 @@ switch(opcode)
OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
if (opcode == OP_UPTO)
{
- OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
}
@@ -8971,7 +8989,7 @@ switch(opcode)
if (opcode == OP_UPTO)
{
- OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, label);
}
else
@@ -9000,7 +9018,7 @@ switch(opcode)
if (opcode == OP_UPTO)
{
- OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, label);
}
else
@@ -9026,7 +9044,7 @@ switch(opcode)
compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
if (opcode == OP_UPTO)
{
- OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, label);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
}
@@ -9113,7 +9131,7 @@ switch(opcode)
label = LABEL();
compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);
- OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, label);
set_jumps(no_match, LABEL());
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);
@@ -9124,7 +9142,7 @@ switch(opcode)
label = LABEL();
detect_partial_match(common, &no_match);
compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
- OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, label);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
set_jumps(no_char1_match, LABEL());
@@ -9142,7 +9160,7 @@ switch(opcode)
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
@@ -9264,7 +9282,7 @@ size = 3 + (size < 0 ? 0 : size);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
allocate_stack(common, size);
if (size > 3)
- OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw));
+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw));
else
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, BACKTRACK_AS(then_trap_backtrack)->start);
@@ -9569,7 +9587,7 @@ while (cc < ccend)
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return;
}
if (cc == NULL)
@@ -9677,7 +9695,7 @@ switch(opcode)
case OP_MINUPTO:
OP1(SLJIT_MOV, TMP1, 0, base, offset1);
OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
- OP2(SLJIT_SUB | SLJIT_SET_E, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
add_jump(compiler, &jumplist, JUMP(SLJIT_ZERO));
OP1(SLJIT_MOV, base, offset1, TMP1, 0);
@@ -9723,7 +9741,7 @@ switch(opcode)
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
@@ -9831,7 +9849,7 @@ if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK)
{
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr);
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_backtrack)->framesize * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(assert_backtrack)->framesize - 1));
set_jumps(current->topbacktracks, LABEL());
}
@@ -9841,7 +9859,7 @@ else
if (bra == OP_BRAZERO)
{
/* We know there is enough place on the stack. */
- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->matchingpath);
JUMPHERE(brajump);
@@ -9954,7 +9972,7 @@ else if (ket == OP_KETRMIN)
else
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
- CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 2), CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
}
/* Drop STR_PTR for non-greedy plus quantifier. */
if (opcode != OP_ONCE)
@@ -10060,7 +10078,7 @@ if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
{
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr);
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-assert->framesize - 1));
}
cond = JUMP(SLJIT_JUMP);
set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL());
@@ -10201,7 +10219,7 @@ if (has_alternatives)
{
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr);
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-assert->framesize - 1));
}
JUMPHERE(cond);
}
@@ -10256,7 +10274,7 @@ else if (opcode == OP_ONCE)
JUMPHERE(once);
/* Restore previous private_data_ptr */
if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_backtrack)->u.framesize * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 1));
else if (ket == OP_KETRMIN)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
@@ -10346,7 +10364,7 @@ if (current->topbacktracks)
free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
JUMPHERE(jump);
}
-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_sw));
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracketpos_backtrack)->framesize - 1));
}
static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current)
@@ -10392,10 +10410,10 @@ if (opcode == OP_THEN || opcode == OP_THEN_ARG)
jump = JUMP(SLJIT_JUMP);
loop = LABEL();
- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), -(int)sizeof(sljit_sw));
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
JUMPHERE(jump);
- CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(2 * sizeof(sljit_sw)), TMP1, 0, loop);
- CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(3 * sizeof(sljit_sw)), TMP2, 0, loop);
+ CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0, loop);
+ CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0, loop);
add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP));
return;
}
@@ -10645,7 +10663,7 @@ while (current)
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
current = current->prev;
@@ -10684,7 +10702,7 @@ sljit_emit_fast_enter(compiler, TMP2, 0);
count_match(common);
allocate_stack(common, private_data_size + framesize + alternativesize);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0);
-copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head);
+copy_private_data(common, ccbegin, ccend, TRUE, framesize + alternativesize, private_data_size + framesize + alternativesize, needs_control_head);
if (needs_control_head)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, STACK_TOP, 0);
@@ -10737,9 +10755,9 @@ if (common->quit != NULL)
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);
if (needs_frame)
{
- OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
- add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
}
OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
common->quit = NULL;
@@ -10750,32 +10768,32 @@ set_jumps(common->accept, LABEL());
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);
if (needs_frame)
{
- OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
- add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
}
OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);
JUMPHERE(jump);
if (common->quit != NULL)
set_jumps(common->quit, LABEL());
-copy_private_data(common, ccbegin, ccend, FALSE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head);
+copy_private_data(common, ccbegin, ccend, FALSE, framesize + alternativesize, private_data_size + framesize + alternativesize, needs_control_head);
free_stack(common, private_data_size + framesize + alternativesize);
if (needs_control_head)
{
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 2 * sizeof(sljit_sw));
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-3));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP1, 0);
OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0);
}
else
{
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));
OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP2, 0);
}
-sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0);
+sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), STACK(-1));
}
#undef COMPILE_BACKTRACKINGPATH
@@ -11237,7 +11255,7 @@ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0);
-OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);
+OP2(SLJIT_SUB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);
sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
jump = CMP(SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
@@ -11391,10 +11409,10 @@ union {
sljit_u8 local_space[MACHINE_STACK_SIZE];
struct sljit_stack local_stack;
-local_stack.top = (sljit_sw)&local_space;
-local_stack.base = local_stack.top;
-local_stack.limit = local_stack.base + MACHINE_STACK_SIZE;
-local_stack.max_limit = local_stack.limit;
+local_stack.max_limit = local_space;
+local_stack.limit = local_space;
+local_stack.base = local_space + MACHINE_STACK_SIZE;
+local_stack.top = local_space + MACHINE_STACK_SIZE;
arguments->stack = &local_stack;
convert_executable_func.executable_func = executable_func;
return convert_executable_func.call_executable_func(arguments);
diff --git a/pcre/pcre_scanner_unittest.cc b/pcre/pcre_scanner_unittest.cc
index c00312c4f63..623e2afda80 100644
--- a/pcre/pcre_scanner_unittest.cc
+++ b/pcre/pcre_scanner_unittest.cc
@@ -57,6 +57,7 @@
} while (0)
using std::vector;
+using std::string;
using pcrecpp::StringPiece;
using pcrecpp::Scanner;
diff --git a/pcre/pcre_stringpiece.h.in b/pcre/pcre_stringpiece.h.in
index eb25826b453..f54f3f3b31b 100644
--- a/pcre/pcre_stringpiece.h.in
+++ b/pcre/pcre_stringpiece.h.in
@@ -52,12 +52,12 @@
#include
+namespace pcrecpp {
+
using std::memcmp;
using std::strlen;
using std::string;
-namespace pcrecpp {
-
class PCRECPP_EXP_DEFN StringPiece {
private:
const char* ptr_;
diff --git a/pcre/pcre_stringpiece_unittest.cc b/pcre/pcre_stringpiece_unittest.cc
index 1c4759da3b0..88e73a1f976 100644
--- a/pcre/pcre_stringpiece_unittest.cc
+++ b/pcre/pcre_stringpiece_unittest.cc
@@ -24,6 +24,7 @@
} \
} while (0)
+using std::string;
using pcrecpp::StringPiece;
static void CheckSTLComparator() {
diff --git a/pcre/pcre_tables.c b/pcre/pcre_tables.c
index 4960af57c4d..5e18e8cf904 100644
--- a/pcre/pcre_tables.c
+++ b/pcre/pcre_tables.c
@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2012 University of Cambridge
+ Copyright (c) 1997-2017 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -161,7 +161,7 @@ const pcre_uint32 PRIV(ucp_gbtable[]) = {
(1<
#include "pcrecpp.h"
+using std::string;
using pcrecpp::StringPiece;
using pcrecpp::RE;
using pcrecpp::RE_Options;
diff --git a/pcre/pcregrep.c b/pcre/pcregrep.c
index fd2a67622ba..317f7454e13 100644
--- a/pcre/pcregrep.c
+++ b/pcre/pcregrep.c
@@ -1804,11 +1804,6 @@ while (ptr < endptr)
if (line_buffered) fflush(stdout);
rc = 0; /* Had some success */
- /* If the current match ended past the end of the line (only possible
- in multiline mode), we are done with this line. */
-
- if ((unsigned int)offsets[1] > linelength) goto END_ONE_MATCH;
-
startoffset = offsets[1]; /* Restart after the match */
if (startoffset <= oldstartoffset)
{
@@ -1818,6 +1813,22 @@ while (ptr < endptr)
if (utf8)
while ((matchptr[startoffset] & 0xc0) == 0x80) startoffset++;
}
+
+ /* If the current match ended past the end of the line (only possible
+ in multiline mode), we must move on to the line in which it did end
+ before searching for more matches. */
+
+ while (startoffset > (int)linelength)
+ {
+ matchptr = ptr += linelength + endlinelength;
+ filepos += (int)(linelength + endlinelength);
+ linenumber++;
+ startoffset -= (int)(linelength + endlinelength);
+ t = end_of_line(ptr, endptr, &endlinelength);
+ linelength = t - ptr - endlinelength;
+ length = (size_t)(endptr - ptr);
+ }
+
goto ONLY_MATCHING_RESTART;
}
}
@@ -3179,9 +3190,11 @@ for (j = 1, cp = patterns; cp != NULL; j++, cp = cp->next)
cp->hint = pcre_study(cp->compiled, study_options, &error);
if (error != NULL)
{
- char s[16];
- if (patterns->next == NULL) s[0] = 0; else sprintf(s, " number %d", j);
- fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);
+ if (patterns->next == NULL)
+ fprintf(stderr, "pcregrep: Error while studying regex: %s\n", error);
+ else
+ fprintf(stderr, "pcregrep: Error while studying regex number %d: %s\n",
+ j, error);
goto EXIT2;
}
#ifdef SUPPORT_PCREGREP_JIT
diff --git a/pcre/pcreposix.c b/pcre/pcreposix.c
index cf75588c40d..7b404a71100 100644
--- a/pcre/pcreposix.c
+++ b/pcre/pcreposix.c
@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2016 University of Cambridge
+ Copyright (c) 1997-2017 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -389,8 +389,8 @@ if (rc >= 0)
{
for (i = 0; i < (size_t)rc; i++)
{
- pmatch[i].rm_so = ovector[i*2];
- pmatch[i].rm_eo = ovector[i*2+1];
+ pmatch[i].rm_so = ovector[i*2] + so;
+ pmatch[i].rm_eo = ovector[i*2+1] + so;
}
if (allocated_ovector) free(ovector);
for (; i < nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1;
diff --git a/pcre/pcretest.c b/pcre/pcretest.c
index 5b73a918075..f1303037281 100644
--- a/pcre/pcretest.c
+++ b/pcre/pcretest.c
@@ -177,7 +177,7 @@ that differ in their output from isprint() even in the "C" locale. */
#define PRINTABLE(c) ((c) >= 32 && (c) < 127)
#endif
-#define PRINTOK(c) (locale_set? isprint(c) : PRINTABLE(c))
+#define PRINTOK(c) (locale_set? (((c) < 256) && isprint(c)) : PRINTABLE(c))
/* Posix support is disabled in 16 or 32 bit only mode. */
#if !defined SUPPORT_PCRE8 && !defined NOPOSIX
@@ -426,11 +426,11 @@ argument, the casting might be incorrectly applied. */
#define PCRE_COPY_NAMED_SUBSTRING32(rc, re, bptr, offsets, count, \
namesptr, cbuffer, size) \
rc = pcre32_copy_named_substring((pcre32 *)re, (PCRE_SPTR32)bptr, offsets, \
- count, (PCRE_SPTR32)namesptr, (PCRE_UCHAR32 *)cbuffer, size/2)
+ count, (PCRE_SPTR32)namesptr, (PCRE_UCHAR32 *)cbuffer, size/4)
#define PCRE_COPY_SUBSTRING32(rc, bptr, offsets, count, i, cbuffer, size) \
rc = pcre32_copy_substring((PCRE_SPTR32)bptr, offsets, count, i, \
- (PCRE_UCHAR32 *)cbuffer, size/2)
+ (PCRE_UCHAR32 *)cbuffer, size/4)
#define PCRE_DFA_EXEC32(count, re, extra, bptr, len, start_offset, options, \
offsets, size_offsets, workspace, size_workspace) \
@@ -4834,7 +4834,16 @@ while (!done)
continue;
case 'O':
- while(isdigit(*p)) n = n * 10 + *p++ - '0';
+ while(isdigit(*p))
+ {
+ if (n > (INT_MAX-10)/10) /* Hack to stop fuzzers */
+ {
+ printf("** \\O argument is too big\n");
+ yield = 1;
+ goto EXIT;
+ }
+ n = n * 10 + *p++ - '0';
+ }
if (n > size_offsets_max)
{
size_offsets_max = n;
diff --git a/pcre/sljit/sljitConfig.h b/pcre/sljit/sljitConfig.h
index eb9c6089f8e..b65584a4afd 100644
--- a/pcre/sljit/sljitConfig.h
+++ b/pcre/sljit/sljitConfig.h
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -90,7 +90,7 @@
/* Executable code allocation:
If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should
- define SLJIT_MALLOC_EXEC, SLJIT_FREE_EXEC, and SLJIT_ENABLE_EXEC. */
+ define SLJIT_MALLOC_EXEC, SLJIT_FREE_EXEC, and SLJIT_EXEC_OFFSET. */
#ifndef SLJIT_EXECUTABLE_ALLOCATOR
/* Enabled by default. */
#define SLJIT_EXECUTABLE_ALLOCATOR 1
diff --git a/pcre/sljit/sljitConfigInternal.h b/pcre/sljit/sljitConfigInternal.h
index 4dc452fb54d..cc0810fbd7a 100644
--- a/pcre/sljit/sljitConfigInternal.h
+++ b/pcre/sljit/sljitConfigInternal.h
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -187,14 +187,6 @@
/* External function definitions. */
/**********************************/
-#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)
-
-/* These libraries are needed for the macros below. */
-#include
-#include
-
-#endif /* SLJIT_STD_MACROS_DEFINED */
-
/* General macros:
Note: SLJIT is designed to be independent from them as possible.
@@ -304,6 +296,13 @@
#define SLJIT_CACHE_FLUSH(from, to) \
sys_icache_invalidate((char*)(from), (char*)(to) - (char*)(from))
+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+
+/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
+#define SLJIT_CACHE_FLUSH(from, to) \
+ ppc_cache_flush((from), (to))
+#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
+
#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
#define SLJIT_CACHE_FLUSH(from, to) \
@@ -316,13 +315,6 @@
#define SLJIT_CACHE_FLUSH(from, to) \
cacheflush((long)(from), (long)(to), 0)
-#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
-
-/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
-#define SLJIT_CACHE_FLUSH(from, to) \
- ppc_cache_flush((from), (to))
-#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
-
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */
@@ -401,7 +393,9 @@ typedef double sljit_f64;
#ifndef SLJIT_W
/* Defining long constants. */
-#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+#define SLJIT_W(w) (w##l)
+#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
#define SLJIT_W(w) (w##ll)
#else
#define SLJIT_W(w) (w)
@@ -547,10 +541,10 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
#define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr)
#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
-SLJIT_API_FUNC_ATTRIBUTE void sljit_enable_exec(void* from, void *to);
-#define SLJIT_ENABLE_EXEC(from, to) sljit_enable_exec((from), (to))
+SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
+#define SLJIT_EXEC_OFFSET(ptr) sljit_exec_offset(ptr)
#else
-#define SLJIT_ENABLE_EXEC(from, to)
+#define SLJIT_EXEC_OFFSET(ptr) 0
#endif
#endif
@@ -561,37 +555,37 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_enable_exec(void* from, void *to);
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-#define SLJIT_NUMBER_OF_REGISTERS 10
-#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
+#define SLJIT_NUMBER_OF_REGISTERS 12
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 9
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
-#define SLJIT_LOCALS_OFFSET_BASE ((2 + 4) * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
#else
/* Maximum 3 arguments are passed on the stack, +1 for double alignment. */
-#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1 + 4) * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
#endif /* SLJIT_X86_32_FASTCALL */
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
#ifndef _WIN64
-#define SLJIT_NUMBER_OF_REGISTERS 12
+#define SLJIT_NUMBER_OF_REGISTERS 13
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 6
-#define SLJIT_LOCALS_OFFSET_BASE (sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE 0
#else
-#define SLJIT_NUMBER_OF_REGISTERS 12
+#define SLJIT_NUMBER_OF_REGISTERS 13
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
-#define SLJIT_LOCALS_OFFSET_BASE ((4 + 2) * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
#endif /* _WIN64 */
#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
-#define SLJIT_NUMBER_OF_REGISTERS 11
+#define SLJIT_NUMBER_OF_REGISTERS 12
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
#define SLJIT_LOCALS_OFFSET_BASE 0
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
-#define SLJIT_NUMBER_OF_REGISTERS 11
-#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
+#define SLJIT_NUMBER_OF_REGISTERS 12
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
#define SLJIT_LOCALS_OFFSET_BASE 0
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
@@ -615,7 +609,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_enable_exec(void* from, void *to);
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
-#define SLJIT_NUMBER_OF_REGISTERS 17
+#define SLJIT_NUMBER_OF_REGISTERS 21
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#define SLJIT_LOCALS_OFFSET_BASE (4 * sizeof(sljit_sw))
@@ -671,7 +665,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_enable_exec(void* from, void *to);
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
-#if !defined(SLJIT_ASSERT) || !defined(SLJIT_ASSERT_STOP)
+#if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)
/* SLJIT_HALT_PROCESS must halt the process. */
#ifndef SLJIT_HALT_PROCESS
@@ -683,7 +677,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_enable_exec(void* from, void *to);
#include
-#endif /* !SLJIT_ASSERT || !SLJIT_ASSERT_STOP */
+#endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */
/* Feel free to redefine these two macros. */
#ifndef SLJIT_ASSERT
@@ -698,34 +692,33 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_enable_exec(void* from, void *to);
#endif /* !SLJIT_ASSERT */
-#ifndef SLJIT_ASSERT_STOP
+#ifndef SLJIT_UNREACHABLE
-#define SLJIT_ASSERT_STOP() \
+#define SLJIT_UNREACHABLE() \
do { \
printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \
SLJIT_HALT_PROCESS(); \
} while (0)
-#endif /* !SLJIT_ASSERT_STOP */
+#endif /* !SLJIT_UNREACHABLE */
#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
/* Forcing empty, but valid statements. */
#undef SLJIT_ASSERT
-#undef SLJIT_ASSERT_STOP
+#undef SLJIT_UNREACHABLE
#define SLJIT_ASSERT(x) \
do { } while (0)
-#define SLJIT_ASSERT_STOP() \
+#define SLJIT_UNREACHABLE() \
do { } while (0)
#endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
#ifndef SLJIT_COMPILE_ASSERT
-/* Should be improved eventually. */
#define SLJIT_COMPILE_ASSERT(x, description) \
- SLJIT_ASSERT(x)
+ switch(0) { case 0: case ((x) ? 1 : 0): break; }
#endif /* !SLJIT_COMPILE_ASSERT */
diff --git a/pcre/sljit/sljitExecAllocator.c b/pcre/sljit/sljitExecAllocator.c
index 54f05f5dd70..f5009788f62 100644
--- a/pcre/sljit/sljitExecAllocator.c
+++ b/pcre/sljit/sljitExecAllocator.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -86,7 +86,7 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
}
-static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
+static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
{
SLJIT_UNUSED_ARG(size);
VirtualFree(chunk, 0, MEM_RELEASE);
@@ -96,7 +96,7 @@ static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
{
- void* retval;
+ void *retval;
#ifdef MAP_ANON
retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
@@ -111,7 +111,7 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
return (retval != MAP_FAILED) ? retval : NULL;
}
-static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
+static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
{
munmap(chunk, size);
}
@@ -180,8 +180,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
sljit_uw chunk_size;
allocator_grab_lock();
- if (size < sizeof(struct free_block))
- size = sizeof(struct free_block);
+ if (size < (64 - sizeof(struct block_header)))
+ size = (64 - sizeof(struct block_header));
size = ALIGN_SIZE(size);
free_block = free_blocks;
diff --git a/pcre/sljit/sljitLir.c b/pcre/sljit/sljitLir.c
index a6ecc010288..66cdda3db42 100644
--- a/pcre/sljit/sljitLir.c
+++ b/pcre/sljit/sljitLir.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -26,6 +26,14 @@
#include "sljitLir.h"
+#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)
+
+/* These libraries are needed for the macros below. */
+#include
+#include
+
+#endif /* SLJIT_STD_MACROS_DEFINED */
+
#define CHECK_ERROR() \
do { \
if (SLJIT_UNLIKELY(compiler->error)) \
@@ -76,14 +84,18 @@
#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
-#define GET_OPCODE(op) \
- ((op) & ~(SLJIT_I32_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
+#define VARIABLE_FLAG_SHIFT (10)
+#define VARIABLE_FLAG_MASK (0x3f << VARIABLE_FLAG_SHIFT)
+#define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT)
-#define GET_FLAGS(op) \
- ((op) & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C))
+#define GET_OPCODE(op) \
+ ((op) & ~(SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK))
+
+#define HAS_FLAGS(op) \
+ ((op) & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))
#define GET_ALL_FLAGS(op) \
- ((op) & (SLJIT_I32_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
+ ((op) & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK))
#define TYPE_CAST_NEEDED(op) \
(((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16) || ((op) >= SLJIT_MOVU_U8 && (op) <= SLJIT_MOVU_S16))
@@ -251,6 +263,12 @@
#endif
+#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
+#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr) + (exec_offset))
+#else
+#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr))
+#endif
+
/* Argument checking features. */
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -289,13 +307,6 @@
} \
} while (0)
-#define CHECK_DYN_CODE_MOD(extra_check) \
- if ((extra_check) && !sljit_is_dyn_code_modification_enabled()) \
- { \
- compiler->error = SLJIT_ERR_DYN_CODE_MOD; \
- return NULL; \
- }
-
#elif (defined SLJIT_DEBUG && SLJIT_DEBUG)
/* Assertion failure occures if an invalid argument is passed. */
@@ -308,7 +319,6 @@
#define CHECK(x) x
#define CHECK_PTR(x) x
#define CHECK_REG_INDEX(x) x
-#define CHECK_DYN_CODE_MOD(extra_check) SLJIT_ASSERT(!(extra_check) || sljit_is_dyn_code_modification_enabled())
#elif (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
@@ -318,7 +328,6 @@
#define CHECK(x) x
#define CHECK_PTR(x) x
#define CHECK_REG_INDEX(x) x
-#define CHECK_DYN_CODE_MOD(extra_check)
#else
@@ -326,7 +335,6 @@
#define CHECK(x)
#define CHECK_PTR(x)
#define CHECK_REG_INDEX(x)
-#define CHECK_DYN_CODE_MOD(extra_check)
#endif /* SLJIT_ARGUMENT_CHECKS */
@@ -334,7 +342,7 @@
/* Public functions */
/* --------------------------------------------------------------------- */
-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
#define SLJIT_NEEDS_COMPILER_INIT 1
static sljit_s32 compiler_initialized = 0;
/* A thread safe initialization. */
@@ -361,6 +369,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo
int_op_and_single_op_must_be_the_same);
SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_F32_OP,
rewritable_jump_and_single_op_must_not_be_the_same);
+ SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_EQUAL_F64 & 0x1) && !(SLJIT_JUMP & 0x1),
+ conditional_flags_must_be_even_numbers);
/* Only the non-zero members must be set. */
compiler->error = SLJIT_SUCCESS;
@@ -457,15 +467,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compi
compiler->error = SLJIT_ERR_ALLOC_FAILED;
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_dyn_code_modification_enabled(void)
-{
-#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \
- && (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
- return 0;
-#endif
- return 1;
-}
-
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
{
@@ -504,6 +505,18 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
}
}
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(current_flags);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_I32_OP | SLJIT_SET_Z)) == 0) {
+ compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_I32_OP | SLJIT_SET_Z));
+ }
+#endif
+}
+
/* --------------------------------------------------------------------- */
/* Private functions */
/* --------------------------------------------------------------------- */
@@ -649,65 +662,6 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
(((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-#define FUNCTION_CHECK_OP() \
- CHECK_ARGUMENT(!GET_FLAGS(op) || !(op & SLJIT_KEEP_FLAGS)); \
- switch (GET_OPCODE(op)) { \
- case SLJIT_NOT: \
- case SLJIT_CLZ: \
- case SLJIT_AND: \
- case SLJIT_OR: \
- case SLJIT_XOR: \
- case SLJIT_SHL: \
- case SLJIT_LSHR: \
- case SLJIT_ASHR: \
- CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C))); \
- break; \
- case SLJIT_NEG: \
- CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))); \
- break; \
- case SLJIT_MUL: \
- CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))); \
- break; \
- case SLJIT_ADD: \
- CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_S))); \
- break; \
- case SLJIT_SUB: \
- break; \
- case SLJIT_ADDC: \
- case SLJIT_SUBC: \
- CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O))); \
- break; \
- case SLJIT_BREAKPOINT: \
- case SLJIT_NOP: \
- case SLJIT_LMUL_UW: \
- case SLJIT_LMUL_SW: \
- case SLJIT_MOV: \
- case SLJIT_MOV_U32: \
- case SLJIT_MOV_P: \
- case SLJIT_MOVU: \
- case SLJIT_MOVU_U32: \
- case SLJIT_MOVU_P: \
- /* Nothing allowed */ \
- CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
- break; \
- default: \
- /* Only SLJIT_I32_OP or SLJIT_F32_OP is allowed. */ \
- CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
- break; \
- }
-
-#define FUNCTION_CHECK_FOP() \
- CHECK_ARGUMENT(!GET_FLAGS(op) || !(op & SLJIT_KEEP_FLAGS)); \
- switch (GET_OPCODE(op)) { \
- case SLJIT_CMP_F64: \
- CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
- CHECK_ARGUMENT((op & (SLJIT_SET_E | SLJIT_SET_S))); \
- break; \
- default: \
- /* Only SLJIT_I32_OP or SLJIT_F32_OP is allowed. */ \
- CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
- break; \
- }
#define FUNCTION_CHECK_IS_REG(r) \
(((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) || \
@@ -743,12 +697,12 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
CHECK_ARGUMENT(!((i) & ~0x3)); \
} \
- CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
+ CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
}
-#define FUNCTION_CHECK_DST(p, i) \
+#define FUNCTION_CHECK_DST(p, i, unused) \
CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); \
- if (FUNCTION_CHECK_IS_REG_OR_UNUSED(p)) \
+ if (FUNCTION_CHECK_IS_REG(p) || ((unused) && (p) == SLJIT_UNUSED)) \
CHECK_ARGUMENT((i) == 0); \
else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
CHECK_ARGUMENT((i) >= 0 && (i) < compiler->logical_local_size); \
@@ -762,7 +716,7 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
CHECK_ARGUMENT(!((i) & ~0x3)); \
} \
- CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
+ CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
}
#define FUNCTION_FCHECK(p, i) \
@@ -782,15 +736,7 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
CHECK_ARGUMENT(((p) & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SP) && !(i & ~0x3)); \
} \
- CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
- }
-
-#define FUNCTION_CHECK_OP1() \
- if (GET_OPCODE(op) >= SLJIT_MOVU && GET_OPCODE(op) <= SLJIT_MOVU_P) { \
- CHECK_ARGUMENT(!(src & SLJIT_MEM) || (src & REG_MASK) != SLJIT_SP); \
- CHECK_ARGUMENT(!(dst & SLJIT_MEM) || (dst & REG_MASK) != SLJIT_SP); \
- if ((src & SLJIT_MEM) && (src & REG_MASK)) \
- CHECK_ARGUMENT((dst & REG_MASK) != (src & REG_MASK) && OFFS_REG(dst) != (src & REG_MASK)); \
+ CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
}
#endif /* SLJIT_ARGUMENT_CHECKS */
@@ -816,8 +762,10 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
do { \
if ((r) < (SLJIT_R0 + compiler->scratches)) \
fprintf(compiler->verbose, "r%d", (r) - SLJIT_R0); \
- else \
+ else if ((r) != SLJIT_SP) \
fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - (r)); \
+ else \
+ fprintf(compiler->verbose, "sp"); \
} while (0)
#define sljit_verbose_param(compiler, p, i) \
@@ -910,6 +858,7 @@ static char* jump_names[] = {
(char*)"sig_greater", (char*)"sig_less_equal",
(char*)"overflow", (char*)"not_overflow",
(char*)"mul_overflow", (char*)"mul_not_overflow",
+ (char*)"carry", (char*)"",
(char*)"equal", (char*)"not_equal",
(char*)"less", (char*)"greater_equal",
(char*)"greater", (char*)"less_equal",
@@ -954,7 +903,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
SLJIT_UNUSED_ARG(compiler);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(!(options & ~SLJIT_DOUBLE_ALIGNMENT));
+ CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT));
CHECK_ARGUMENT(args >= 0 && args <= 3);
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);
@@ -964,6 +913,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
+ compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
@@ -977,13 +927,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
- if (SLJIT_UNLIKELY(compiler->skip_checks)) {
- compiler->skip_checks = 0;
- CHECK_RETURN_OK;
- }
-
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(!(options & ~SLJIT_DOUBLE_ALIGNMENT));
+ CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT));
CHECK_ARGUMENT(args >= 0 && args <= 3);
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);
@@ -993,6 +938,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
+ compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
@@ -1012,6 +958,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi
}
else
CHECK_ARGUMENT(src == 0 && srcw == 0);
+ compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1030,7 +977,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- FUNCTION_CHECK_DST(dst, dstw);
+ FUNCTION_CHECK_DST(dst, dstw, 0);
+ compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1046,6 +994,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_return(struct sljit_
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
FUNCTION_CHECK_SRC(src, srcw);
+ compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1063,6 +1012,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler
CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW)
|| ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW));
CHECK_ARGUMENT(op < SLJIT_LMUL_UW || compiler->scratches >= 2);
+ if (op >= SLJIT_LMUL_UW)
+ compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
@@ -1088,10 +1039,49 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CLZ);
- FUNCTION_CHECK_OP();
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_NOT:
+ /* Only SLJIT_I32_OP and SLJIT_SET_Z are allowed. */
+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
+ break;
+ case SLJIT_NEG:
+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+ || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
+ break;
+ case SLJIT_MOV:
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_P:
+ case SLJIT_MOVU:
+ case SLJIT_MOVU_U32:
+ case SLJIT_MOVU_P:
+ /* Nothing allowed */
+ CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+ break;
+ default:
+ /* Only SLJIT_I32_OP is allowed. */
+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+ break;
+ }
+
+ FUNCTION_CHECK_DST(dst, dstw, 1);
FUNCTION_CHECK_SRC(src, srcw);
- FUNCTION_CHECK_DST(dst, dstw);
- FUNCTION_CHECK_OP1();
+
+ if (GET_OPCODE(op) >= SLJIT_NOT)
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
+ else if (GET_OPCODE(op) >= SLJIT_MOVU) {
+ CHECK_ARGUMENT(!(src & SLJIT_MEM) || (src & REG_MASK) != SLJIT_SP);
+ CHECK_ARGUMENT(!(dst & SLJIT_MEM) || (dst & REG_MASK) != SLJIT_SP);
+ if ((src & REG_MASK) != SLJIT_UNUSED) {
+ CHECK_ARGUMENT((src & REG_MASK) != (dst & REG_MASK) && (src & REG_MASK) != OFFS_REG(dst));
+ CHECK_ARGUMENT((src & OFFS_REG_MASK) == SLJIT_UNUSED || srcw == 0);
+ }
+ if ((dst & REG_MASK) != SLJIT_UNUSED) {
+ CHECK_ARGUMENT((dst & REG_MASK) != OFFS_REG(src));
+ CHECK_ARGUMENT((dst & OFFS_REG_MASK) == SLJIT_UNUSED || dstw == 0);
+ }
+ compiler->last_flags = 0;
+ }
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1102,9 +1092,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
}
else
{
- fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & SLJIT_I32_OP) ? "" : "32",
- !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s",
- !(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
+ fprintf(compiler->verbose, " %s%s%s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & SLJIT_I32_OP) ? "" : "32",
+ !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",
+ !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);
}
sljit_verbose_param(compiler, dst, dstw);
@@ -1128,16 +1118,53 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ASHR);
- FUNCTION_CHECK_OP();
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_AND:
+ case SLJIT_OR:
+ case SLJIT_XOR:
+ case SLJIT_SHL:
+ case SLJIT_LSHR:
+ case SLJIT_ASHR:
+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
+ break;
+ case SLJIT_MUL:
+ CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+ || GET_FLAG_TYPE(op) == SLJIT_MUL_OVERFLOW);
+ break;
+ case SLJIT_ADD:
+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+ || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)
+ || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
+ break;
+ case SLJIT_SUB:
+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+ || (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_OVERFLOW)
+ || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
+ break;
+ case SLJIT_ADDC:
+ case SLJIT_SUBC:
+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+ || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
+ CHECK_ARGUMENT((compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
+ CHECK_ARGUMENT((op & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP));
+ break;
+ default:
+ SLJIT_UNREACHABLE();
+ break;
+ }
+
+ FUNCTION_CHECK_DST(dst, dstw, 1);
FUNCTION_CHECK_SRC(src1, src1w);
FUNCTION_CHECK_SRC(src2, src2w);
- FUNCTION_CHECK_DST(dst, dstw);
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_I32_OP) ? "" : "32",
- !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s",
- !(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
+ fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_I32_OP) ? "" : "32",
+ !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",
+ !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, src1, src1w);
@@ -1178,6 +1205,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_co
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(instruction);
+
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
CHECK_ARGUMENT(size > 0 && size < 16);
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
@@ -1187,6 +1215,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_co
CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0);
#endif
+ compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1209,9 +1238,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compile
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(sljit_is_fpu_available());
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV_F64 && GET_OPCODE(op) <= SLJIT_ABS_F64);
- FUNCTION_CHECK_FOP();
+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
FUNCTION_FCHECK(src, srcw);
FUNCTION_FCHECK(dst, dstw);
#endif
@@ -1237,22 +1266,31 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
+#endif
+
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(sljit_is_fpu_available());
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_CMP_F64);
- FUNCTION_CHECK_FOP();
+ CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
+ CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK)
+ || (GET_FLAG_TYPE(op) >= SLJIT_EQUAL_F64 && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_F64));
FUNCTION_FCHECK(src1, src1w);
FUNCTION_FCHECK(src2, src2w);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " %s%s%s%s ", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64",
- (op & SLJIT_SET_E) ? ".e" : "", (op & SLJIT_SET_S) ? ".s" : "");
+ fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64");
+ if (op & VARIABLE_FLAG_MASK) {
+ fprintf(compiler->verbose, ".%s_f", jump_names[GET_FLAG_TYPE(op)]);
+ }
+ fprintf(compiler->verbose, " ");
sljit_verbose_fparam(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src2, src2w);
@@ -1272,11 +1310,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(str
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(sljit_is_fpu_available());
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CONV_S32_FROM_F64);
- FUNCTION_CHECK_FOP();
+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
FUNCTION_FCHECK(src, srcw);
- FUNCTION_CHECK_DST(dst, dstw);
+ FUNCTION_CHECK_DST(dst, dstw, 0);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1302,9 +1340,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_sw(str
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(sljit_is_fpu_available());
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_F64_FROM_SW && GET_OPCODE(op) <= SLJIT_CONV_F64_FROM_S32);
- FUNCTION_CHECK_FOP();
+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
FUNCTION_CHECK_SRC(src, srcw);
FUNCTION_FCHECK(dst, dstw);
#endif
@@ -1328,9 +1366,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compile
sljit_s32 src2, sljit_sw src2w)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(sljit_is_fpu_available());
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD_F64 && GET_OPCODE(op) <= SLJIT_DIV_F64);
- FUNCTION_CHECK_FOP();
+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
FUNCTION_FCHECK(src1, src1w);
FUNCTION_FCHECK(src2, src2w);
FUNCTION_FCHECK(dst, dstw);
@@ -1353,6 +1391,15 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compil
{
SLJIT_UNUSED_ARG(compiler);
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->last_flags = 0;
+#endif
+
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
fprintf(compiler->verbose, "label:\n");
@@ -1369,9 +1416,20 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));
+ CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_CALL3);
CHECK_ARGUMENT((type & 0xff) < SLJIT_JUMP || !(type & SLJIT_I32_OP));
CHECK_ARGUMENT((type & 0xff) <= SLJIT_CALL0 || ((type & 0xff) - SLJIT_CALL0) <= compiler->scratches);
+
+ if ((type & 0xff) < SLJIT_JUMP) {
+ if ((type & 0xff) <= SLJIT_NOT_ZERO)
+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
+ else
+ CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)
+ || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)
+ || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));
+ CHECK_ARGUMENT((type & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP));
+ }
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
@@ -1390,6 +1448,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_SIG_LESS_EQUAL);
FUNCTION_CHECK_SRC(src1, src1w);
FUNCTION_CHECK_SRC(src2, src2w);
+ compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1409,11 +1468,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile
sljit_s32 src2, sljit_sw src2w)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(sljit_is_fpu_available());
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_F32_OP)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL_F64 && (type & 0xff) <= SLJIT_ORDERED_F64);
FUNCTION_FCHECK(src1, src1w);
FUNCTION_FCHECK(src2, src2w);
+ compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1430,6 +1490,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->last_flags = 0;
+#endif
+
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
compiler->skip_checks = 0;
CHECK_RETURN_OK;
@@ -1452,46 +1516,80 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compil
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src, sljit_sw srcw,
sljit_s32 type)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);
- CHECK_ARGUMENT(op == SLJIT_MOV || GET_OPCODE(op) == SLJIT_MOV_U32 || GET_OPCODE(op) == SLJIT_MOV_S32
+ CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1));
+ CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32
|| (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR));
- CHECK_ARGUMENT((op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C)) == 0);
- CHECK_ARGUMENT((op & (SLJIT_SET_E | SLJIT_KEEP_FLAGS)) != (SLJIT_SET_E | SLJIT_KEEP_FLAGS));
- if (GET_OPCODE(op) < SLJIT_ADD) {
- CHECK_ARGUMENT(src == SLJIT_UNUSED && srcw == 0);
- } else {
- CHECK_ARGUMENT(src == dst && srcw == dstw);
- }
- FUNCTION_CHECK_DST(dst, dstw);
+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
+
+ if ((type & 0xff) <= SLJIT_NOT_ZERO)
+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
+ else
+ CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)
+ || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)
+ || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));
+
+ FUNCTION_CHECK_DST(dst, dstw, 0);
+
+ if (GET_OPCODE(op) >= SLJIT_ADD)
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " flags %s%s%s%s, ",
- !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k",
+ fprintf(compiler->verbose, " flags%s %s%s, ",
+ !(op & SLJIT_SET_Z) ? "" : ".z",
GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],
GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_I32_OP) ? "32" : ""));
sljit_verbose_param(compiler, dst, dstw);
- if (src != SLJIT_UNUSED) {
- fprintf(compiler->verbose, ", ");
- sljit_verbose_param(compiler, src, srcw);
- }
fprintf(compiler->verbose, ", %s%s\n", jump_names[type & 0xff], JUMP_POSTFIX(type));
}
#endif
CHECK_RETURN_OK;
}
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));
+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP));
+ if (src != SLJIT_IMM) {
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src));
+ }
+
+ if ((type & 0xff) <= SLJIT_NOT_ZERO)
+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
+ else
+ CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)
+ || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)
+ || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " cmov%s %s%s, ",
+ !(dst_reg & SLJIT_I32_OP) ? "" : ".i",
+ jump_names[type & 0xff], JUMP_POSTFIX(type));
+ sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif
+ CHECK_RETURN_OK;
+}
+
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
{
SLJIT_UNUSED_ARG(offset);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- FUNCTION_CHECK_DST(dst, dstw);
+ FUNCTION_CHECK_DST(dst, dstw, 0);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1508,7 +1606,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil
SLJIT_UNUSED_ARG(init_value);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- FUNCTION_CHECK_DST(dst, dstw);
+ FUNCTION_CHECK_DST(dst, dstw, 0);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1569,6 +1667,44 @@ static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *comp
return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);
}
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
+ || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
+ || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1))
+
+static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ sljit_s32 op = (dst_reg & SLJIT_I32_OP) ? SLJIT_MOV32 : SLJIT_MOV;
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+ jump = sljit_emit_jump(compiler, type ^ 0x1);
+ FAIL_IF(!jump);
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+ FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_I32_OP, 0, src, srcw));
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+ label = sljit_emit_label(compiler);
+ FAIL_IF(!label);
+ sljit_set_label(jump, label);
+ return SLJIT_SUCCESS;
+}
+
+#endif
+
/* CPU description section */
#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
@@ -1626,7 +1762,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
sljit_sw tmp_srcw;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
condition = type & 0xff;
@@ -1671,6 +1806,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
condition = SLJIT_SIG_GREATER_EQUAL;
break;
}
+
type = condition | (type & (SLJIT_I32_OP | SLJIT_REWRITABLE_JUMP));
tmp_src = src1;
src1 = src2;
@@ -1681,11 +1817,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
}
if (condition <= SLJIT_NOT_ZERO)
- flags = SLJIT_SET_E;
- else if (condition <= SLJIT_LESS_EQUAL)
- flags = SLJIT_SET_U;
+ flags = SLJIT_SET_Z;
else
- flags = SLJIT_SET_S;
+ flags = condition << VARIABLE_FLAG_SHIFT;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -1697,39 +1831,31 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
- return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP));
+ return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));
}
+#endif
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- sljit_s32 flags, condition;
-
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));
- condition = type & 0xff;
- flags = (condition <= SLJIT_NOT_EQUAL_F64) ? SLJIT_SET_E : SLJIT_SET_S;
- if (type & SLJIT_F32_OP)
- flags |= SLJIT_F32_OP;
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_I32_OP), src1, src1w, src2, src2w);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
- sljit_emit_fop1(compiler, SLJIT_CMP_F64 | flags, src1, src1w, src2, src2w);
-
-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- compiler->skip_checks = 1;
-#endif
- return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP));
+ return sljit_emit_jump(compiler, type);
}
-#endif
-
#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
@@ -1743,7 +1869,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
compiler->skip_checks = 1;
#endif
if (offset != 0)
- return sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
+ return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0);
}
@@ -1758,23 +1884,30 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
return "unsupported";
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data)
{
- SLJIT_ASSERT_STOP();
+ SLJIT_UNUSED_ARG(allocator_data);
+ SLJIT_UNREACHABLE();
return NULL;
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)
{
SLJIT_UNUSED_ARG(compiler);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNREACHABLE();
}
SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(size);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return NULL;
}
@@ -1783,21 +1916,28 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(verbose);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
#endif
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
{
SLJIT_UNUSED_ARG(compiler);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return NULL;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ SLJIT_UNUSED_ARG(feature_type);
+ SLJIT_UNREACHABLE();
+ return 0;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
{
SLJIT_UNUSED_ARG(code);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
@@ -1812,7 +1952,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
SLJIT_UNUSED_ARG(fscratches);
SLJIT_UNUSED_ARG(fsaveds);
SLJIT_UNUSED_ARG(local_size);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
@@ -1828,7 +1968,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
SLJIT_UNUSED_ARG(fscratches);
SLJIT_UNUSED_ARG(fsaveds);
SLJIT_UNUSED_ARG(local_size);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
@@ -1838,7 +1978,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
SLJIT_UNUSED_ARG(op);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
@@ -1847,7 +1987,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(dst);
SLJIT_UNUSED_ARG(dstw);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
@@ -1856,7 +1996,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
@@ -1864,7 +2004,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
@@ -1878,7 +2018,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
SLJIT_UNUSED_ARG(dstw);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
@@ -1895,13 +2035,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
SLJIT_UNUSED_ARG(src1w);
SLJIT_UNUSED_ARG(src2);
SLJIT_UNUSED_ARG(src2w);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
{
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return reg;
}
@@ -1911,14 +2051,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(instruction);
SLJIT_UNUSED_ARG(size);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
{
- SLJIT_ASSERT_STOP();
- return 0;
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(current_flags);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
@@ -1931,7 +2071,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
SLJIT_UNUSED_ARG(dstw);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
@@ -1948,14 +2088,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
SLJIT_UNUSED_ARG(src1w);
SLJIT_UNUSED_ARG(src2);
SLJIT_UNUSED_ARG(src2w);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
{
SLJIT_UNUSED_ARG(compiler);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return NULL;
}
@@ -1963,7 +2103,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return NULL;
}
@@ -1977,7 +2117,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
SLJIT_UNUSED_ARG(src1w);
SLJIT_UNUSED_ARG(src2);
SLJIT_UNUSED_ARG(src2w);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return NULL;
}
@@ -1991,7 +2131,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
SLJIT_UNUSED_ARG(src1w);
SLJIT_UNUSED_ARG(src2);
SLJIT_UNUSED_ARG(src2w);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return NULL;
}
@@ -1999,14 +2139,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sl
{
SLJIT_UNUSED_ARG(jump);
SLJIT_UNUSED_ARG(label);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)
{
SLJIT_UNUSED_ARG(jump);
SLJIT_UNUSED_ARG(target);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
@@ -2015,23 +2155,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
SLJIT_UNUSED_ARG(type);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src, sljit_sw srcw,
sljit_s32 type)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
SLJIT_UNUSED_ARG(dst);
SLJIT_UNUSED_ARG(dstw);
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNREACHABLE();
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNUSED_ARG(dst_reg);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
- SLJIT_UNUSED_ARG(type);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
@@ -2041,7 +2191,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
SLJIT_UNUSED_ARG(dst);
SLJIT_UNUSED_ARG(dstw);
SLJIT_UNUSED_ARG(offset);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
@@ -2051,22 +2201,24 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
SLJIT_UNUSED_ARG(dst);
SLJIT_UNUSED_ARG(dstw);
SLJIT_UNUSED_ARG(initval);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return NULL;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
SLJIT_UNUSED_ARG(addr);
- SLJIT_UNUSED_ARG(new_addr);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNUSED_ARG(new_target);
+ SLJIT_UNUSED_ARG(executable_offset);
+ SLJIT_UNREACHABLE();
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
SLJIT_UNUSED_ARG(addr);
SLJIT_UNUSED_ARG(new_constant);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNUSED_ARG(executable_offset);
+ SLJIT_UNREACHABLE();
}
#endif
diff --git a/pcre/sljit/sljitLir.h b/pcre/sljit/sljitLir.h
index facddb65de7..a58ad6e6387 100644
--- a/pcre/sljit/sljitLir.h
+++ b/pcre/sljit/sljitLir.h
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -120,8 +120,8 @@ of sljitConfigInternal.h */
If an architecture provides two scratch and three saved registers,
its scratch and saved register sets are the following:
- R0 | [S4] | R0 and S4 represent the same physical register
- R1 | [S3] | R1 and S3 represent the same physical register
+ R0 | | R0 is always a scratch register
+ R1 | | R1 is always a scratch register
[R2] | S2 | R2 and S2 represent the same physical register
[R3] | S1 | R3 and S1 represent the same physical register
[R4] | S0 | R4 and S0 represent the same physical register
@@ -129,38 +129,35 @@ of sljitConfigInternal.h */
Note: SLJIT_NUMBER_OF_SCRATCH_REGISTERS would be 2 and
SLJIT_NUMBER_OF_SAVED_REGISTERS would be 3 for this architecture.
- Note: On all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 10
- and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 5. However, 4 registers
+ Note: On all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 12
+ and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 6. However, 6 registers
are virtual on x86-32. See below.
- The purpose of this definition is convenience. Although a register
- is either scratch register or saved register, SLJIT allows accessing
- them from the other set. For example, four registers can be used as
- scratch registers and the fifth one as saved register on the architecture
- above. Of course the last two scratch registers (R2 and R3) from this
- four will be saved on the stack, because they are defined as saved
- registers in the application binary interface. Still R2 and R3 can be
- used for referencing to these registers instead of S2 and S1, which
- makes easier to write platform independent code. Scratch registers
- can be saved registers in a similar way, but these extra saved
- registers will not be preserved across function calls! Hence the
- application must save them on those platforms, where the number of
- saved registers is too low. This can be done by copy them onto
- the stack and restore them after a function call.
+ The purpose of this definition is convenience: saved registers can
+ be used as extra scratch registers. For example four registers can
+ be specified as scratch registers and the fifth one as saved register
+ on the CPU above and any user code which requires four scratch
+ registers can run unmodified. The SLJIT compiler automatically saves
+ the content of the two extra scrath register on the stack. Scratch
+ registers can also be preserved by saving their value on the stack
+ but this needs to be done manually.
Note: To emphasize that registers assigned to R2-R4 are saved
- registers, they are enclosed by square brackets. S3-S4
- are marked in a similar way.
+ registers, they are enclosed by square brackets.
Note: sljit_emit_enter and sljit_set_context defines whether a register
is S or R register. E.g: when 3 scratches and 1 saved is mapped
by sljit_emit_enter, the allowed register set will be: R0-R2 and
S0. Although S2 is mapped to the same position as R2, it does not
- available in the current configuration. Furthermore the R3 (S1)
- register does not available as well.
+ available in the current configuration. Furthermore the S1 register
+ is not available at all.
*/
-/* When SLJIT_UNUSED is specified as destination, the result is discarded. */
+/* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1 and
+ and sljit_emit_op2 operations the result is discarded. If no status
+ flags are set, no instructions are emitted for these operations. Data
+ prefetch is a special exception, see SLJIT_MOV operation. Other SLJIT
+ operations do not support SLJIT_UNUSED as a destination operand. */
#define SLJIT_UNUSED 0
/* Scratch registers. */
@@ -325,19 +322,22 @@ struct sljit_compiler {
sljit_s32 local_size;
/* Code size. */
sljit_uw size;
- /* For statistical purposes. */
+ /* Relative offset of the executable mapping from the writable mapping. */
+ sljit_uw executable_offset;
+ /* Executable size for statistical purposes. */
sljit_uw executable_size;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
sljit_s32 args;
+ sljit_s32 locals_offset;
+ sljit_s32 saveds_offset;
#endif
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
sljit_s32 mode32;
+#ifdef _WIN64
+ sljit_s32 locals_offset;
#endif
-
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
- sljit_s32 flags_saved;
#endif
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
@@ -354,13 +354,6 @@ struct sljit_compiler {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
/* Temporary fields. */
sljit_uw shift_imm;
- sljit_s32 cache_arg;
- sljit_sw cache_argw;
-#endif
-
-#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
- sljit_s32 cache_arg;
- sljit_sw cache_argw;
#endif
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
@@ -397,6 +390,9 @@ struct sljit_compiler {
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|| (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ /* Flags specified by the last arithmetic instruction.
+ It contains the type of the variable flag. */
+ sljit_s32 last_flags;
/* Local size passed to the functions. */
sljit_s32 logical_local_size;
#endif
@@ -404,6 +400,7 @@ struct sljit_compiler {
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|| (defined SLJIT_DEBUG && SLJIT_DEBUG) \
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ /* Trust arguments when the API function is called. */
sljit_s32 skip_checks;
#endif
};
@@ -457,10 +454,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compile
SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose);
#endif
-/* Returns with non-zero if dynamic code modification is enabled. */
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_dyn_code_modification_enabled(void);
-
/*
Create executable code from the sljit instruction stream. This is the final step
of the code generation so no more instructions can be added after this call.
@@ -473,15 +466,55 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code);
/*
- After the machine code generation is finished we can retrieve the allocated
- executable memory size, although this area may not be fully filled with
- instructions depending on some optimizations. This function is useful only
- for statistical purposes.
+ When the protected executable allocator is used the JIT code is mapped
+ twice. The first mapping has read/write and the second mapping has read/exec
+ permissions. This function returns with the relative offset of the executable
+ mapping using the writable mapping as the base after the machine code is
+ successfully generated. The returned value is always 0 for the normal executable
+ allocator, since it uses only one mapping with read/write/exec permissions.
+ Dynamic code modifications requires this value.
+
+ Before a successful code generation, this function returns with 0.
+*/
+static SLJIT_INLINE sljit_sw sljit_get_executable_offset(struct sljit_compiler *compiler) { return compiler->executable_offset; }
+
+/*
+ The executable memory consumption of the generated code can be retrieved by
+ this function. The returned value can be used for statistical purposes.
Before a successful code generation, this function returns with 0.
*/
static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; }
+/* Returns with non-zero if the feature or limitation type passed as its
+ argument is present on the current CPU.
+
+ Some features (e.g. floating point operations) require hardware (CPU)
+ support while others (e.g. move with update) are emulated if not available.
+ However even if a feature is emulated, specialized code paths can be faster
+ than the emulation. Some limitations are emulated as well so their general
+ case is supported but it has extra performance costs. */
+
+/* [Not emulated] Floating-point support is available. */
+#define SLJIT_HAS_FPU 0
+/* [Limitation] Some registers are virtual registers. */
+#define SLJIT_HAS_VIRTUAL_REGISTERS 1
+/* [Emulated] Some forms of move with pre update is supported. */
+#define SLJIT_HAS_PRE_UPDATE 2
+/* [Emulated] Count leading zero is supported. */
+#define SLJIT_HAS_CLZ 3
+/* [Emulated] Conditional move is supported. */
+#define SLJIT_HAS_CMOV 4
+/* [Limitation] [Emulated] Shifting with register is limited to SLJIT_PREF_SHIFT_REG. */
+#define SLJIT_HAS_PREF_SHIFT_REG 5
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+/* [Not emulated] SSE2 support is available on x86. */
+#define SLJIT_HAS_SSE2 100
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type);
+
/* Instruction generation. Returns with any error code. If there is no
error, they return with SLJIT_SUCCESS. */
@@ -526,8 +559,8 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
*/
/* The absolute address returned by sljit_get_local_base with
-offset 0 is aligned to sljit_d. Otherwise it is aligned to sljit_uw. */
-#define SLJIT_DOUBLE_ALIGNMENT 0x00000001
+offset 0 is aligned to sljit_f64. Otherwise it is aligned to sljit_sw. */
+#define SLJIT_F64_ALIGNMENT 0x00000001
/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */
#define SLJIT_MAX_LOCAL_SIZE 65536
@@ -569,7 +602,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
and setting up a new stack frame would cost too much performance. However, it is still
possible to return to the address of the caller (or anywhere else). */
-/* Note: flags are not changed (unlike sljit_emit_enter / sljit_emit_return). */
+/* Note: may destroy flags. */
/* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested,
since many architectures do clever branch prediction on call / return instruction pairs. */
@@ -638,57 +671,97 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
#define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 8))
#define SLJIT_IMM 0x40
-/* Set 32 bit operation mode (I) on 64 bit CPUs. This flag is ignored on 32
- bit CPUs. When this flag is set for an arithmetic operation, only the
- lower 32 bit of the input register(s) are used, and the CPU status flags
- are set according to the 32 bit result. Although the higher 32 bit of
- the input and the result registers are not defined by SLJIT, it might be
- defined by the CPU architecture (e.g. MIPS). To satisfy these requirements
- all source registers must be computed by operations where this flag is
- also set. In other words 32 and 64 bit arithmetic operations cannot be
- mixed. The only exception is SLJIT_IMOV and SLJIT_IMOVU whose source
- register can hold any 32 or 64 bit value. This source register is
- converted to a 32 bit compatible format. SLJIT does not generate any
- instructions on certain CPUs (e.g. on x86 and ARM) if the source and
- destination operands are the same registers. Affects sljit_emit_op0,
- sljit_emit_op1 and sljit_emit_op2. */
+/* Set 32 bit operation mode (I) on 64 bit CPUs. This option is ignored on
+ 32 bit CPUs. When this option is set for an arithmetic operation, only
+ the lower 32 bit of the input registers are used, and the CPU status
+ flags are set according to the 32 bit result. Although the higher 32 bit
+ of the input and the result registers are not defined by SLJIT, it might
+ be defined by the CPU architecture (e.g. MIPS). To satisfy these CPU
+ requirements all source registers must be the result of those operations
+ where this option was also set. Memory loads read 32 bit values rather
+ than 64 bit ones. In other words 32 bit and 64 bit operations cannot
+ be mixed. The only exception is SLJIT_MOV32 and SLJIT_MOVU32 whose source
+ register can hold any 32 or 64 bit value, and it is converted to a 32 bit
+ compatible format first. This conversion is free (no instructions are
+ emitted) on most CPUs. A 32 bit value can also be coverted to a 64 bit
+ value by SLJIT_MOV_S32 (sign extension) or SLJIT_MOV_U32 (zero extension).
+
+ Note: memory addressing always uses 64 bit values on 64 bit systems so
+ the result of a 32 bit operation must not be used with SLJIT_MEMx
+ macros.
+
+ This option is part of the instruction name, so there is no need to
+ manually set it. E.g:
+
+ SLJIT_ADD32 == (SLJIT_ADD | SLJIT_I32_OP) */
#define SLJIT_I32_OP 0x100
-/* F32 precision mode (SP). This flag is similar to SLJIT_I32_OP, just
- it applies to floating point registers (it is even the same bit). When
- this flag is passed, the CPU performs 32 bit floating point operations.
- Similar to SLJIT_I32_OP, all register arguments must be computed by
- floating point operations where this flag is also set. Affects
- sljit_emit_fop1, sljit_emit_fop2 and sljit_emit_fcmp. */
-#define SLJIT_F32_OP 0x100
+/* Set F32 (single) precision mode for floating-point computation. This
+ option is similar to SLJIT_I32_OP, it just applies to floating point
+ registers. When this option is passed, the CPU performs 32 bit floating
+ point operations, rather than 64 bit one. Similar to SLJIT_I32_OP, all
+ register arguments must be the result of those operations where this
+ option was also set.
-/* Common CPU status flags for all architectures (x86, ARM, PPC)
- - carry flag
- - overflow flag
- - zero flag
- - negative/positive flag (depends on arc)
- On mips, these flags are emulated by software. */
+ This option is part of the instruction name, so there is no need to
+ manually set it. E.g:
-/* By default, the instructions may, or may not set the CPU status flags.
- Forcing to set or keep status flags can be done with the following flags: */
+ SLJIT_MOV_F32 = (SLJIT_MOV_F64 | SLJIT_F32_OP)
+ */
+#define SLJIT_F32_OP SLJIT_I32_OP
-/* Note: sljit tries to emit the minimum number of instructions. Using these
- flags can increase them, so use them wisely to avoid unnecessary code generation. */
+/* Many CPUs (x86, ARM, PPC) has status flags which can be set according
+ to the result of an operation. Other CPUs (MIPS) does not have status
+ flags, and results must be stored in registers. To cover both architecture
+ types efficiently only two flags are defined by SLJIT:
-/* Set Equal (Zero) status flag (E). */
-#define SLJIT_SET_E 0x0200
-/* Set unsigned status flag (U). */
-#define SLJIT_SET_U 0x0400
-/* Set signed status flag (S). */
-#define SLJIT_SET_S 0x0800
-/* Set signed overflow flag (O). */
-#define SLJIT_SET_O 0x1000
-/* Set carry flag (C).
- Note: Kinda unsigned overflow, but behaves differently on various cpus. */
-#define SLJIT_SET_C 0x2000
-/* Do not modify the flags (K).
- Note: This flag cannot be combined with any other SLJIT_SET_* flag. */
-#define SLJIT_KEEP_FLAGS 0x4000
+ * Zero (equal) flag: it is set if the result is zero
+ * Variable flag: its value is defined by the last arithmetic operation
+
+ SLJIT instructions can set any or both of these flags. The value of
+ these flags is undefined if the instruction does not specify their value.
+ The description of each instruction contains the list of allowed flag
+ types.
+
+ Example: SLJIT_ADD can set the Z, OVERFLOW, CARRY flags hence
+
+ sljit_op2(..., SLJIT_ADD, ...)
+ Both the zero and variable flags are undefined so they can
+ have any value after the operation is completed.
+
+ sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z, ...)
+ Sets the zero flag if the result is zero, clears it otherwise.
+ The variable flag is undefined.
+
+ sljit_op2(..., SLJIT_ADD | SLJIT_SET_OVERFLOW, ...)
+ Sets the variable flag if an integer overflow occurs, clears
+ it otherwise. The zero flag is undefined.
+
+ sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z | SLJIT_SET_CARRY, ...)
+ Sets the zero flag if the result is zero, clears it otherwise.
+ Sets the variable flag if unsigned overflow (carry) occurs,
+ clears it otherwise.
+
+ If an instruction (e.g. SLJIT_MOV) does not modify flags the flags are
+ unchanged.
+
+ Using these flags can reduce the number of emitted instructions. E.g. a
+ fast loop can be implemented by decreasing a counter register and set the
+ zero flag to jump back if the counter register is not reached zero.
+
+ Motivation: although CPUs can set a large number of flags, usually their
+ values are ignored or only one of them is used. Emulating a large number
+ of flags on systems without flag register is complicated so SLJIT
+ instructions must specify the flag they want to use and only that flag
+ will be emulated. The last arithmetic instruction can be repeated if
+ multiple flags needs to be checked.
+*/
+
+/* Set Zero status flag. */
+#define SLJIT_SET_Z 0x0200
+/* Set the variable status flag if condition is true.
+ See comparison types. */
+#define SLJIT_SET(condition) ((condition) << 10)
/* Notes:
- you cannot postpone conditional jump instructions except if noted that
@@ -698,11 +771,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
/* Starting index of opcodes for sljit_emit_op0. */
#define SLJIT_OP0_BASE 0
-/* Flags: - (never set any flags)
+/* Flags: - (does not modify flags)
Note: breakpoint instruction is not supported by all architectures (e.g. ppc)
It falls back to SLJIT_NOP in those cases. */
#define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0)
-/* Flags: - (never set any flags)
+/* Flags: - (does not modify flags)
Note: may or may not cause an extra cycle wait
it can even decrease the runtime in a few cases. */
#define SLJIT_NOP (SLJIT_OP0_BASE + 1)
@@ -714,13 +787,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
Signed multiplication of SLJIT_R0 and SLJIT_R1.
Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */
#define SLJIT_LMUL_SW (SLJIT_OP0_BASE + 3)
-/* Flags: I - (may destroy flags)
+/* Flags: - (may destroy flags)
Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
Note: if SLJIT_R1 is 0, the behaviour is undefined. */
#define SLJIT_DIVMOD_UW (SLJIT_OP0_BASE + 4)
#define SLJIT_DIVMOD_U32 (SLJIT_DIVMOD_UW | SLJIT_I32_OP)
-/* Flags: I - (may destroy flags)
+/* Flags: - (may destroy flags)
Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
Note: if SLJIT_R1 is 0, the behaviour is undefined.
@@ -728,13 +801,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
the behaviour is undefined. */
#define SLJIT_DIVMOD_SW (SLJIT_OP0_BASE + 5)
#define SLJIT_DIVMOD_S32 (SLJIT_DIVMOD_SW | SLJIT_I32_OP)
-/* Flags: I - (may destroy flags)
+/* Flags: - (may destroy flags)
Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
Note: if SLJIT_R1 is 0, the behaviour is undefined. */
#define SLJIT_DIV_UW (SLJIT_OP0_BASE + 6)
#define SLJIT_DIV_U32 (SLJIT_DIV_UW | SLJIT_I32_OP)
-/* Flags: I - (may destroy flags)
+/* Flags: - (may destroy flags)
Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
Note: if SLJIT_R1 is 0, the behaviour is undefined.
@@ -748,75 +821,113 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
/* Starting index of opcodes for sljit_emit_op1. */
#define SLJIT_OP1_BASE 32
-/* Notes for MOV instructions:
- U = Mov with update (pre form). If source or destination defined as SLJIT_MEM1(r1)
- or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument
- UB = unsigned byte (8 bit)
- SB = signed byte (8 bit)
- UH = unsigned half (16 bit)
- SH = signed half (16 bit)
- UI = unsigned int (32 bit)
- SI = signed int (32 bit)
- P = pointer (sljit_p) size */
+/* The MOV instruction transfer data from source to destination.
-/* Flags: - (never set any flags) */
+ MOV instruction suffixes:
+
+ U8 - unsigned 8 bit data transfer
+ S8 - signed 8 bit data transfer
+ U16 - unsigned 16 bit data transfer
+ S16 - signed 16 bit data transfer
+ U32 - unsigned int (32 bit) data transfer
+ S32 - signed int (32 bit) data transfer
+ P - pointer (sljit_p) data transfer
+
+ U = move with update (pre form). If source or destination defined as
+ SLJIT_MEM1(r1) or SLJIT_MEM2(r1, r2), r1 is increased by the
+ offset part of the address.
+
+ Register arguments and base registers can only be used once for move
+ with update instructions. The shift value of SLJIT_MEM2 addressing
+ mode must also be 0. Reason: SLJIT_MOVU instructions are expected to
+ be in high-performance loops where complex instruction emulation
+ would be too costly.
+
+ Examples for invalid move with update instructions:
+
+ sljit_emit_op1(..., SLJIT_MOVU_U8,
+ SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 8);
+ sljit_emit_op1(..., SLJIT_MOVU_U8,
+ SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_R0, 0);
+ sljit_emit_op1(..., SLJIT_MOVU_U8,
+ SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 0, SLJIT_MEM1(SLJIT_R0), 8);
+ sljit_emit_op1(..., SLJIT_MOVU_U8,
+ SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0);
+ sljit_emit_op1(..., SLJIT_MOVU_U8,
+ SLJIT_R2, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1);
+
+ The following example is valid, since only the offset register is
+ used multiple times:
+
+ sljit_emit_op1(..., SLJIT_MOVU_U8,
+ SLJIT_MEM2(SLJIT_R0, SLJIT_R2), 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0);
+
+ If the destination of a MOV without update instruction is SLJIT_UNUSED
+ and the source operand is a memory address the compiler emits a prefetch
+ instruction if this instruction is supported by the current CPU.
+ Higher data sizes bring the data closer to the core: a MOV with word
+ size loads the data into a higher level cache than a byte size. Otherwise
+ the type does not affect the prefetch instruction. Furthermore a prefetch
+ instruction never fails, so it can be used to prefetch a data from an
+ address and check whether that address is NULL afterwards.
+*/
+
+/* Flags: - (does not modify flags) */
#define SLJIT_MOV (SLJIT_OP1_BASE + 0)
-/* Flags: I - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_MOV_U8 (SLJIT_OP1_BASE + 1)
#define SLJIT_MOV32_U8 (SLJIT_MOV_U8 | SLJIT_I32_OP)
-/* Flags: I - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_MOV_S8 (SLJIT_OP1_BASE + 2)
#define SLJIT_MOV32_S8 (SLJIT_MOV_S8 | SLJIT_I32_OP)
-/* Flags: I - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_MOV_U16 (SLJIT_OP1_BASE + 3)
#define SLJIT_MOV32_U16 (SLJIT_MOV_U16 | SLJIT_I32_OP)
-/* Flags: I - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_MOV_S16 (SLJIT_OP1_BASE + 4)
#define SLJIT_MOV32_S16 (SLJIT_MOV_S16 | SLJIT_I32_OP)
-/* Flags: I - (never set any flags)
+/* Flags: - (does not modify flags)
Note: no SLJIT_MOV32_U32 form, since it is the same as SLJIT_MOV32 */
#define SLJIT_MOV_U32 (SLJIT_OP1_BASE + 5)
-/* Flags: I - (never set any flags)
+/* Flags: - (does not modify flags)
Note: no SLJIT_MOV32_S32 form, since it is the same as SLJIT_MOV32 */
#define SLJIT_MOV_S32 (SLJIT_OP1_BASE + 6)
-/* Flags: I - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_MOV32 (SLJIT_MOV_S32 | SLJIT_I32_OP)
-/* Flags: - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_MOV_P (SLJIT_OP1_BASE + 7)
-/* Flags: - (never set any flags) */
+/* Flags: - (may destroy flags) */
#define SLJIT_MOVU (SLJIT_OP1_BASE + 8)
-/* Flags: I - (never set any flags) */
+/* Flags: - (may destroy flags) */
#define SLJIT_MOVU_U8 (SLJIT_OP1_BASE + 9)
#define SLJIT_MOVU32_U8 (SLJIT_MOVU_U8 | SLJIT_I32_OP)
-/* Flags: I - (never set any flags) */
+/* Flags: - (may destroy flags) */
#define SLJIT_MOVU_S8 (SLJIT_OP1_BASE + 10)
#define SLJIT_MOVU32_S8 (SLJIT_MOVU_S8 | SLJIT_I32_OP)
-/* Flags: I - (never set any flags) */
+/* Flags: - (may destroy flags) */
#define SLJIT_MOVU_U16 (SLJIT_OP1_BASE + 11)
#define SLJIT_MOVU32_U16 (SLJIT_MOVU_U16 | SLJIT_I32_OP)
-/* Flags: I - (never set any flags) */
+/* Flags: - (may destroy flags) */
#define SLJIT_MOVU_S16 (SLJIT_OP1_BASE + 12)
#define SLJIT_MOVU32_S16 (SLJIT_MOVU_S16 | SLJIT_I32_OP)
-/* Flags: I - (never set any flags)
+/* Flags: - (may destroy flags)
Note: no SLJIT_MOVU32_U32 form, since it is the same as SLJIT_MOVU32 */
#define SLJIT_MOVU_U32 (SLJIT_OP1_BASE + 13)
-/* Flags: I - (never set any flags)
+/* Flags: - (may destroy flags)
Note: no SLJIT_MOVU32_S32 form, since it is the same as SLJIT_MOVU32 */
#define SLJIT_MOVU_S32 (SLJIT_OP1_BASE + 14)
-/* Flags: I - (never set any flags) */
+/* Flags: - (may destroy flags) */
#define SLJIT_MOVU32 (SLJIT_MOVU_S32 | SLJIT_I32_OP)
-/* Flags: - (never set any flags) */
+/* Flags: - (may destroy flags) */
#define SLJIT_MOVU_P (SLJIT_OP1_BASE + 15)
-/* Flags: I | E | K */
+/* Flags: Z */
#define SLJIT_NOT (SLJIT_OP1_BASE + 16)
#define SLJIT_NOT32 (SLJIT_NOT | SLJIT_I32_OP)
-/* Flags: I | E | O | K */
+/* Flags: Z | OVERFLOW */
#define SLJIT_NEG (SLJIT_OP1_BASE + 17)
#define SLJIT_NEG32 (SLJIT_NEG | SLJIT_I32_OP)
/* Count leading zeroes
- Flags: I | E | K
- Important note! Sparc 32 does not support K flag, since
- the required popc instruction is introduced only in sparc 64. */
+ Flags: - (may destroy flags) */
#define SLJIT_CLZ (SLJIT_OP1_BASE + 18)
#define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_I32_OP)
@@ -827,46 +938,48 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
/* Starting index of opcodes for sljit_emit_op2. */
#define SLJIT_OP2_BASE 96
-/* Flags: I | E | O | C | K */
+/* Flags: Z | OVERFLOW | CARRY */
#define SLJIT_ADD (SLJIT_OP2_BASE + 0)
#define SLJIT_ADD32 (SLJIT_ADD | SLJIT_I32_OP)
-/* Flags: I | C | K */
+/* Flags: CARRY */
#define SLJIT_ADDC (SLJIT_OP2_BASE + 1)
#define SLJIT_ADDC32 (SLJIT_ADDC | SLJIT_I32_OP)
-/* Flags: I | E | U | S | O | C | K */
+/* Flags: Z | LESS | GREATER_EQUAL | GREATER | LESS_EQUAL
+ SIG_LESS | SIG_GREATER_EQUAL | SIG_GREATER
+ SIG_LESS_EQUAL | CARRY */
#define SLJIT_SUB (SLJIT_OP2_BASE + 2)
#define SLJIT_SUB32 (SLJIT_SUB | SLJIT_I32_OP)
-/* Flags: I | C | K */
+/* Flags: CARRY */
#define SLJIT_SUBC (SLJIT_OP2_BASE + 3)
#define SLJIT_SUBC32 (SLJIT_SUBC | SLJIT_I32_OP)
/* Note: integer mul
- Flags: I | O (see SLJIT_C_MUL_*) | K */
+ Flags: MUL_OVERFLOW */
#define SLJIT_MUL (SLJIT_OP2_BASE + 4)
#define SLJIT_MUL32 (SLJIT_MUL | SLJIT_I32_OP)
-/* Flags: I | E | K */
+/* Flags: Z */
#define SLJIT_AND (SLJIT_OP2_BASE + 5)
#define SLJIT_AND32 (SLJIT_AND | SLJIT_I32_OP)
-/* Flags: I | E | K */
+/* Flags: Z */
#define SLJIT_OR (SLJIT_OP2_BASE + 6)
#define SLJIT_OR32 (SLJIT_OR | SLJIT_I32_OP)
-/* Flags: I | E | K */
+/* Flags: Z */
#define SLJIT_XOR (SLJIT_OP2_BASE + 7)
#define SLJIT_XOR32 (SLJIT_XOR | SLJIT_I32_OP)
-/* Flags: I | E | K
+/* Flags: Z
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
to bit_length - 1, the result is undefined. */
#define SLJIT_SHL (SLJIT_OP2_BASE + 8)
#define SLJIT_SHL32 (SLJIT_SHL | SLJIT_I32_OP)
-/* Flags: I | E | K
+/* Flags: Z
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
to bit_length - 1, the result is undefined. */
#define SLJIT_LSHR (SLJIT_OP2_BASE + 9)
#define SLJIT_LSHR32 (SLJIT_LSHR | SLJIT_I32_OP)
-/* Flags: I | E | K
+/* Flags: Z
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
@@ -879,44 +992,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w);
-/* Returns with non-zero if fpu is available. */
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void);
-
/* Starting index of opcodes for sljit_emit_fop1. */
#define SLJIT_FOP1_BASE 128
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0)
#define SLJIT_MOV_F32 (SLJIT_MOV_F64 | SLJIT_F32_OP)
/* Convert opcodes: CONV[DST_TYPE].FROM[SRC_TYPE]
SRC/DST TYPE can be: D - double, S - single, W - signed word, I - signed int
Rounding mode when the destination is W or I: round towards zero. */
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_CONV_F64_FROM_F32 (SLJIT_FOP1_BASE + 1)
#define SLJIT_CONV_F32_FROM_F64 (SLJIT_CONV_F64_FROM_F32 | SLJIT_F32_OP)
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_CONV_SW_FROM_F64 (SLJIT_FOP1_BASE + 2)
#define SLJIT_CONV_SW_FROM_F32 (SLJIT_CONV_SW_FROM_F64 | SLJIT_F32_OP)
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_CONV_S32_FROM_F64 (SLJIT_FOP1_BASE + 3)
#define SLJIT_CONV_S32_FROM_F32 (SLJIT_CONV_S32_FROM_F64 | SLJIT_F32_OP)
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_CONV_F64_FROM_SW (SLJIT_FOP1_BASE + 4)
#define SLJIT_CONV_F32_FROM_SW (SLJIT_CONV_F64_FROM_SW | SLJIT_F32_OP)
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_CONV_F64_FROM_S32 (SLJIT_FOP1_BASE + 5)
#define SLJIT_CONV_F32_FROM_S32 (SLJIT_CONV_F64_FROM_S32 | SLJIT_F32_OP)
/* Note: dst is the left and src is the right operand for SLJIT_CMPD.
- Note: NaN check is always performed. If SLJIT_C_FLOAT_UNORDERED flag
- is set, the comparison result is unpredictable.
- Flags: SP | E | S (see SLJIT_C_FLOAT_*) */
+ Flags: EQUAL_F | LESS_F | GREATER_EQUAL_F | GREATER_F | LESS_EQUAL_F */
#define SLJIT_CMP_F64 (SLJIT_FOP1_BASE + 6)
#define SLJIT_CMP_F32 (SLJIT_CMP_F64 | SLJIT_F32_OP)
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_NEG_F64 (SLJIT_FOP1_BASE + 7)
#define SLJIT_NEG_F32 (SLJIT_NEG_F64 | SLJIT_F32_OP)
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_ABS_F64 (SLJIT_FOP1_BASE + 8)
#define SLJIT_ABS_F32 (SLJIT_ABS_F64 | SLJIT_F32_OP)
@@ -927,16 +1034,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
/* Starting index of opcodes for sljit_emit_fop2. */
#define SLJIT_FOP2_BASE 160
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_ADD_F64 (SLJIT_FOP2_BASE + 0)
#define SLJIT_ADD_F32 (SLJIT_ADD_F64 | SLJIT_F32_OP)
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_SUB_F64 (SLJIT_FOP2_BASE + 1)
#define SLJIT_SUB_F32 (SLJIT_SUB_F64 | SLJIT_F32_OP)
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_MUL_F64 (SLJIT_FOP2_BASE + 2)
#define SLJIT_MUL_F32 (SLJIT_MUL_F64 | SLJIT_F32_OP)
-/* Flags: SP - (never set any flags) */
+/* Flags: - (does not modify flags) */
#define SLJIT_DIV_F64 (SLJIT_FOP2_BASE + 3)
#define SLJIT_DIV_F32 (SLJIT_DIV_F64 | SLJIT_F32_OP)
@@ -963,56 +1070,77 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
#define SLJIT_LESS 2
#define SLJIT_LESS32 (SLJIT_LESS | SLJIT_I32_OP)
+#define SLJIT_SET_LESS SLJIT_SET(SLJIT_LESS)
#define SLJIT_GREATER_EQUAL 3
#define SLJIT_GREATER_EQUAL32 (SLJIT_GREATER_EQUAL | SLJIT_I32_OP)
+#define SLJIT_SET_GREATER_EQUAL SLJIT_SET(SLJIT_GREATER_EQUAL)
#define SLJIT_GREATER 4
#define SLJIT_GREATER32 (SLJIT_GREATER | SLJIT_I32_OP)
+#define SLJIT_SET_GREATER SLJIT_SET(SLJIT_GREATER)
#define SLJIT_LESS_EQUAL 5
#define SLJIT_LESS_EQUAL32 (SLJIT_LESS_EQUAL | SLJIT_I32_OP)
+#define SLJIT_SET_LESS_EQUAL SLJIT_SET(SLJIT_LESS_EQUAL)
#define SLJIT_SIG_LESS 6
#define SLJIT_SIG_LESS32 (SLJIT_SIG_LESS | SLJIT_I32_OP)
+#define SLJIT_SET_SIG_LESS SLJIT_SET(SLJIT_SIG_LESS)
#define SLJIT_SIG_GREATER_EQUAL 7
#define SLJIT_SIG_GREATER_EQUAL32 (SLJIT_SIG_GREATER_EQUAL | SLJIT_I32_OP)
+#define SLJIT_SET_SIG_GREATER_EQUAL SLJIT_SET(SLJIT_SIG_GREATER_EQUAL)
#define SLJIT_SIG_GREATER 8
#define SLJIT_SIG_GREATER32 (SLJIT_SIG_GREATER | SLJIT_I32_OP)
+#define SLJIT_SET_SIG_GREATER SLJIT_SET(SLJIT_SIG_GREATER)
#define SLJIT_SIG_LESS_EQUAL 9
#define SLJIT_SIG_LESS_EQUAL32 (SLJIT_SIG_LESS_EQUAL | SLJIT_I32_OP)
+#define SLJIT_SET_SIG_LESS_EQUAL SLJIT_SET(SLJIT_SIG_LESS_EQUAL)
#define SLJIT_OVERFLOW 10
#define SLJIT_OVERFLOW32 (SLJIT_OVERFLOW | SLJIT_I32_OP)
+#define SLJIT_SET_OVERFLOW SLJIT_SET(SLJIT_OVERFLOW)
#define SLJIT_NOT_OVERFLOW 11
#define SLJIT_NOT_OVERFLOW32 (SLJIT_NOT_OVERFLOW | SLJIT_I32_OP)
#define SLJIT_MUL_OVERFLOW 12
#define SLJIT_MUL_OVERFLOW32 (SLJIT_MUL_OVERFLOW | SLJIT_I32_OP)
+#define SLJIT_SET_MUL_OVERFLOW SLJIT_SET(SLJIT_MUL_OVERFLOW)
#define SLJIT_MUL_NOT_OVERFLOW 13
#define SLJIT_MUL_NOT_OVERFLOW32 (SLJIT_MUL_NOT_OVERFLOW | SLJIT_I32_OP)
+/* There is no SLJIT_CARRY or SLJIT_NOT_CARRY. */
+#define SLJIT_SET_CARRY SLJIT_SET(14)
+
/* Floating point comparison types. */
-#define SLJIT_EQUAL_F64 14
+#define SLJIT_EQUAL_F64 16
#define SLJIT_EQUAL_F32 (SLJIT_EQUAL_F64 | SLJIT_F32_OP)
-#define SLJIT_NOT_EQUAL_F64 15
+#define SLJIT_SET_EQUAL_F SLJIT_SET(SLJIT_EQUAL_F64)
+#define SLJIT_NOT_EQUAL_F64 17
#define SLJIT_NOT_EQUAL_F32 (SLJIT_NOT_EQUAL_F64 | SLJIT_F32_OP)
-#define SLJIT_LESS_F64 16
+#define SLJIT_SET_NOT_EQUAL_F SLJIT_SET(SLJIT_NOT_EQUAL_F64)
+#define SLJIT_LESS_F64 18
#define SLJIT_LESS_F32 (SLJIT_LESS_F64 | SLJIT_F32_OP)
-#define SLJIT_GREATER_EQUAL_F64 17
+#define SLJIT_SET_LESS_F SLJIT_SET(SLJIT_LESS_F64)
+#define SLJIT_GREATER_EQUAL_F64 19
#define SLJIT_GREATER_EQUAL_F32 (SLJIT_GREATER_EQUAL_F64 | SLJIT_F32_OP)
-#define SLJIT_GREATER_F64 18
+#define SLJIT_SET_GREATER_EQUAL_F SLJIT_SET(SLJIT_GREATER_EQUAL_F64)
+#define SLJIT_GREATER_F64 20
#define SLJIT_GREATER_F32 (SLJIT_GREATER_F64 | SLJIT_F32_OP)
-#define SLJIT_LESS_EQUAL_F64 19
+#define SLJIT_SET_GREATER_F SLJIT_SET(SLJIT_GREATER_F64)
+#define SLJIT_LESS_EQUAL_F64 21
#define SLJIT_LESS_EQUAL_F32 (SLJIT_LESS_EQUAL_F64 | SLJIT_F32_OP)
-#define SLJIT_UNORDERED_F64 20
+#define SLJIT_SET_LESS_EQUAL_F SLJIT_SET(SLJIT_LESS_EQUAL_F64)
+#define SLJIT_UNORDERED_F64 22
#define SLJIT_UNORDERED_F32 (SLJIT_UNORDERED_F64 | SLJIT_F32_OP)
-#define SLJIT_ORDERED_F64 21
+#define SLJIT_SET_UNORDERED_F SLJIT_SET(SLJIT_UNORDERED_F64)
+#define SLJIT_ORDERED_F64 23
#define SLJIT_ORDERED_F32 (SLJIT_ORDERED_F64 | SLJIT_F32_OP)
+#define SLJIT_SET_ORDERED_F SLJIT_SET(SLJIT_ORDERED_F64)
/* Unconditional jump types. */
-#define SLJIT_JUMP 22
-#define SLJIT_FAST_CALL 23
-#define SLJIT_CALL0 24
-#define SLJIT_CALL1 25
-#define SLJIT_CALL2 26
-#define SLJIT_CALL3 27
+#define SLJIT_JUMP 24
+#define SLJIT_FAST_CALL 25
+#define SLJIT_CALL0 26
+#define SLJIT_CALL1 27
+#define SLJIT_CALL2 28
+#define SLJIT_CALL3 29
/* Fast calling method. See sljit_emit_fast_enter / sljit_emit_fast_return. */
@@ -1022,8 +1150,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
/* Emit a jump instruction. The destination is not set, only the type of the jump.
type must be between SLJIT_EQUAL and SLJIT_CALL3
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
- Flags: - (never set any flags) for both conditional and unconditional jumps.
- Flags: destroy all flags for calls. */
+
+ Flags: does not modify flags for conditional and unconditional
+ jumps but destroy all flags for calls. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type);
/* Basic arithmetic comparison. In most architectures it is implemented as
@@ -1033,7 +1162,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
It is suggested to use this comparison form when appropriate.
type must be between SLJIT_EQUAL and SLJIT_I_SIG_LESS_EQUAL
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
- Flags: destroy flags. */
+ Flags: may destroy flags. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w);
@@ -1061,36 +1190,47 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
type must be between SLJIT_JUMP and SLJIT_CALL3
Direct form: set src to SLJIT_IMM() and srcw to the address
Indirect form: any other valid addressing mode
- Flags: - (never set any flags) for unconditional jumps.
- Flags: destroy all flags for calls. */
+
+ Flags: does not modify flags for unconditional jumps but
+ destroy all flags for calls. */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw);
/* Perform the operation using the conditional flags as the second argument.
- Type must always be between SLJIT_EQUAL and SLJIT_S_ORDERED. The value
+ Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_F64. The value
represented by the type is 1, if the condition represented by the type
is fulfilled, and 0 otherwise.
- If op == SLJIT_MOV, SLJIT_MOV_S32, SLJIT_MOV_U32:
+ If op == SLJIT_MOV, SLJIT_MOV32:
Set dst to the value represented by the type (0 or 1).
- Src must be SLJIT_UNUSED, and srcw must be 0
- Flags: - (never set any flags)
+ Flags: - (does not modify flags)
If op == SLJIT_OR, op == SLJIT_AND, op == SLJIT_XOR
- Performs the binary operation using src as the first, and the value
- represented by type as the second argument.
- Important note: only dst=src and dstw=srcw is supported at the moment!
- Flags: I | E | K
- Note: sljit_emit_op_flags does nothing, if dst is SLJIT_UNUSED (regardless of op). */
+ Performs the binary operation using dst as the first, and the value
+ represented by type as the second argument. Result is written into dst.
+ Flags: Z (may destroy flags) */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src, sljit_sw srcw,
sljit_s32 type);
+/* Emit a conditional mov instruction which moves source to destination,
+ if the condition is satisfied. Unlike other arithmetic operations this
+ instruction does not support memory accesses.
+
+ type must be between SLJIT_EQUAL and SLJIT_ORDERED_F64
+ dst_reg must be a valid register and it can be combined
+ with SLJIT_I32_OP to perform a 32 bit arithmetic operation
+ src must be register or immediate (SLJIT_IMM)
+
+ Flags: - (does not modify flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw);
+
/* Copies the base address of SLJIT_SP + offset to dst.
- Flags: - (never set any flags) */
+ Flags: - (may destroy flags) */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset);
/* The constant can be changed runtime (see: sljit_set_const)
- Flags: - (never set any flags) */
+ Flags: - (does not modify flags) */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value);
/* After the code generation the address for label, jump and const instructions
@@ -1100,16 +1240,17 @@ static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { r
static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; }
static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { return const_->addr; }
-/* Only the address is required to rewrite the code. */
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr);
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant);
+/* Only the address and executable offset are required to perform dynamic
+ code modifications. See sljit_get_executable_offset function. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset);
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset);
/* --------------------------------------------------------------------- */
/* Miscellaneous utility functions */
/* --------------------------------------------------------------------- */
#define SLJIT_MAJOR_VERSION 0
-#define SLJIT_MINOR_VERSION 93
+#define SLJIT_MINOR_VERSION 94
/* Get the human readable name of the platform. Can be useful on platforms
like ARM, where ARM and Thumb2 functions can be mixed, and
@@ -1127,19 +1268,23 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void);
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
-/* The sljit_stack is a utiliy feature of sljit, which allocates a
- writable memory region between base (inclusive) and limit (exclusive).
- Both base and limit is a pointer, and base is always <= than limit.
- This feature uses the "address space reserve" feature
- of modern operating systems. Basically we don't need to allocate a
- huge memory block in one step for the worst case, we can start with
- a smaller chunk and extend it later. Since the address space is
- reserved, the data never copied to other regions, thus it is safe
- to store pointers here. */
+/* The sljit_stack is a utility extension of sljit, which provides
+ a top-down stack. The stack starts at base and goes down to
+ max_limit, so the memory region for this stack is between
+ max_limit (inclusive) and base (exclusive). However the
+ application can only use the region between limit (inclusive)
+ and base (exclusive). The sljit_stack_resize can be used to
+ extend this region up to max_limit.
-/* Note: The base field is aligned to PAGE_SIZE bytes (usually 4k or more).
- Note: stack growing should not happen in small steps: 4k, 16k or even
- bigger growth is better.
+ This feature uses the "address space reserve" feature of modern
+ operating systems, so instead of allocating a huge memory block
+ applications can allocate a small region and extend it later
+ without moving the memory area. Hence pointers can be stored
+ in this area. */
+
+/* Note: base and max_limit fields are aligned to PAGE_SIZE bytes
+ (usually 4 Kbyte or more).
+ Note: stack should grow in larger steps, e.g. 4Kbyte, 16Kbyte or more.
Note: this structure may not be supported by all operating systems.
Some kind of fallback mechanism is suggested when SLJIT_UTIL_STACK
is not defined. */
@@ -1147,15 +1292,16 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void);
struct sljit_stack {
/* User data, anything can be stored here.
Starting with the same value as base. */
- sljit_uw top;
+ sljit_u8 *top;
/* These members are read only. */
- sljit_uw base;
- sljit_uw limit;
- sljit_uw max_limit;
+ sljit_u8 *base;
+ sljit_u8 *limit;
+ sljit_u8 *max_limit;
};
/* Returns NULL if unsuccessful.
- Note: limit and max_limit contains the size for stack allocation.
+ Note: max_limit contains the maximum stack size in bytes.
+ Note: limit contains the starting stack size in bytes.
Note: the top field is initialized to base.
Note: see sljit_create_compiler for the explanation of allocator_data. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data);
@@ -1167,7 +1313,7 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack *st
since the growth ratio can be added to the current limit, and sljit_stack_resize
will do all the necessary checks. The fields of the stack are not changed if
sljit_stack_resize fails. */
-SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_uw new_limit);
+SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_limit);
#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */
@@ -1196,6 +1342,15 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct
#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+/* Free unused executable memory. The allocator keeps some free memory
+ around to reduce the number of OS executable memory allocations.
+ This improves performance since these calls are costly. However
+ it is sometimes desired to free all unused memory regions, e.g.
+ before the application terminates. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
+#endif
+
/* --------------------------------------------------------------------- */
/* CPU specific functions */
/* --------------------------------------------------------------------- */
@@ -1228,32 +1383,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
void *instruction, sljit_s32 size);
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+/* Define the currently available CPU status flags. It is usually used after an
+ sljit_emit_op_custom call to define which flags are set. */
-/* Returns with non-zero if sse2 is available. */
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_sse2_available(void);
-
-/* Returns with non-zero if cmov instruction is available. */
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_cmov_available(void);
-
-/* Emit a conditional mov instruction on x86 CPUs. This instruction
- moves src to destination, if the condition is satisfied. Unlike
- other arithmetic instructions, destination must be a register.
- Before such instructions are emitted, cmov support should be
- checked by sljit_x86_is_cmov_available function.
- type must be between SLJIT_EQUAL and SLJIT_S_ORDERED
- dst_reg must be a valid register and it can be combined
- with SLJIT_I32_OP to perform 32 bit arithmetic
- Flags: I - (never set any flags)
- */
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_emit_cmov(struct sljit_compiler *compiler,
- sljit_s32 type,
- sljit_s32 dst_reg,
- sljit_s32 src, sljit_sw srcw);
-
-#endif
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler,
+ sljit_s32 current_flags);
#endif /* _SLJIT_LIR_H_ */
diff --git a/pcre/sljit/sljitNativeARM_32.c b/pcre/sljit/sljitNativeARM_32.c
index a756f82933f..745da99f614 100644
--- a/pcre/sljit/sljitNativeARM_32.c
+++ b/pcre/sljit/sljitNativeARM_32.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -38,8 +38,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
/* Last register + 1. */
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
-#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
-#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 5)
+#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4)
#define TMP_FREG1 (0)
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
@@ -55,8 +54,8 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
(((max_diff) / (sljit_s32)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))
/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
-static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
- 0, 0, 1, 2, 11, 10, 9, 8, 7, 6, 5, 4, 13, 3, 12, 14, 15
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
+ 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 14, 12, 15
};
#define RM(rm) (reg_map[rm])
@@ -83,6 +82,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
#define BLX 0xe12fff30
#define BX 0xe12fff10
#define CLZ 0xe16f0f10
+#define CMN_DP 0xb
#define CMP_DP 0xa
#define BKPT 0xe1200070
#define EOR_DP 0x1
@@ -260,7 +260,7 @@ static SLJIT_INLINE sljit_s32 emit_blx(struct sljit_compiler *compiler)
{
/* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */
SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092));
- return push_inst(compiler, BLX | RM(TMP_REG1));
+ return push_inst(compiler, BLX | RM(TMP_REG2));
}
static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size)
@@ -389,7 +389,7 @@ static SLJIT_INLINE sljit_s32 emit_imm(struct sljit_compiler *compiler, sljit_s3
#endif
-static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code)
+static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code, sljit_sw executable_offset)
{
sljit_sw diff;
@@ -401,7 +401,7 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw
code_ptr--;
if (jump->flags & JUMP_ADDR)
- diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2));
+ diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset);
else {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2));
@@ -426,7 +426,7 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw
}
#else
if (jump->flags & JUMP_ADDR)
- diff = ((sljit_sw)jump->u.target - (sljit_sw)code_ptr);
+ diff = ((sljit_sw)jump->u.target - (sljit_sw)code_ptr - executable_offset);
else {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)code_ptr);
@@ -446,26 +446,28 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw
return 0;
}
-static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, sljit_s32 flush)
+static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw executable_offset, sljit_uw new_addr, sljit_s32 flush_cache)
{
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- sljit_uw *ptr = (sljit_uw*)addr;
- sljit_uw *inst = (sljit_uw*)ptr[0];
+ sljit_uw *ptr = (sljit_uw *)jump_ptr;
+ sljit_uw *inst = (sljit_uw *)ptr[0];
sljit_uw mov_pc = ptr[1];
sljit_s32 bl = (mov_pc & 0x0000f000) != RD(TMP_PC);
- sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2)) >> 2);
+ sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2) - executable_offset) >> 2);
if (diff <= 0x7fffff && diff >= -0x800000) {
/* Turn to branch. */
if (!bl) {
inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff);
- if (flush) {
+ if (flush_cache) {
+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 1);
}
} else {
inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff);
inst[1] = NOP;
- if (flush) {
+ if (flush_cache) {
+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
}
@@ -479,12 +481,14 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr,
if (*inst != mov_pc) {
inst[0] = mov_pc;
if (!bl) {
- if (flush) {
+ if (flush_cache) {
+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 1);
}
} else {
inst[1] = BLX | RM(TMP_REG1);
- if (flush) {
+ if (flush_cache) {
+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
}
@@ -492,11 +496,12 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr,
*ptr = new_addr;
}
#else
- sljit_uw *inst = (sljit_uw*)addr;
+ sljit_uw *inst = (sljit_uw*)jump_ptr;
SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
inst[0] = MOVW | (inst[0] & 0xf000) | ((new_addr << 4) & 0xf0000) | (new_addr & 0xfff);
inst[1] = MOVT | (inst[1] & 0xf000) | ((new_addr >> 12) & 0xf0000) | ((new_addr >> 16) & 0xfff);
- if (flush) {
+ if (flush_cache) {
+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
#endif
@@ -504,7 +509,7 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr,
static sljit_uw get_imm(sljit_uw imm);
-static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant, sljit_s32 flush)
+static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_offset, sljit_sw new_constant, sljit_s32 flush_cache)
{
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
sljit_uw *ptr = (sljit_uw*)addr;
@@ -515,7 +520,8 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant,
src2 = get_imm(new_constant);
if (src2) {
*inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2;
- if (flush) {
+ if (flush_cache) {
+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 1);
}
return;
@@ -524,7 +530,8 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant,
src2 = get_imm(~new_constant);
if (src2) {
*inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2;
- if (flush) {
+ if (flush_cache) {
+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 1);
}
return;
@@ -537,7 +544,8 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant,
if (*inst != ldr_literal) {
*inst = ldr_literal;
- if (flush) {
+ if (flush_cache) {
+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 1);
}
}
@@ -547,7 +555,8 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant,
SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
inst[0] = MOVW | (inst[0] & 0xf000) | ((new_constant << 4) & 0xf0000) | (new_constant & 0xfff);
inst[1] = MOVT | (inst[1] & 0xf000) | ((new_constant >> 12) & 0xf0000) | ((new_constant >> 16) & 0xfff);
- if (flush) {
+ if (flush_cache) {
+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
#endif
@@ -562,6 +571,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_uw *buf_end;
sljit_uw size;
sljit_uw word_count;
+ sljit_sw executable_offset;
+ sljit_sw jump_addr;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
sljit_uw cpool_size;
sljit_uw cpool_skip_alignment;
@@ -602,14 +613,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
if (label && label->size == 0) {
- label->addr = (sljit_uw)code;
- label->size = 0;
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
label = label->next;
}
@@ -636,7 +647,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
cpool_size = 0;
if (label && label->size == word_count) {
/* Points after the current instruction. */
- label->addr = (sljit_uw)code_ptr;
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = code_ptr - code;
label = label->next;
}
@@ -652,19 +663,19 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
if (jump && jump->addr == word_count) {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- if (detect_jump_type(jump, code_ptr, code))
+ if (detect_jump_type(jump, code_ptr, code, executable_offset))
code_ptr--;
jump->addr = (sljit_uw)code_ptr;
#else
jump->addr = (sljit_uw)(code_ptr - 2);
- if (detect_jump_type(jump, code_ptr, code))
+ if (detect_jump_type(jump, code_ptr, code, executable_offset))
code_ptr -= 2;
#endif
jump = jump->next;
}
if (label && label->size == word_count) {
/* code_ptr can be affected above. */
- label->addr = (sljit_uw)(code_ptr + 1);
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);
label->size = (code_ptr + 1) - code;
label = label->next;
}
@@ -729,17 +740,18 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = compiler->jumps;
while (jump) {
- buf_ptr = (sljit_uw*)jump->addr;
+ buf_ptr = (sljit_uw *)jump->addr;
if (jump->flags & PATCH_B) {
+ jump_addr = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
if (!(jump->flags & JUMP_ADDR)) {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - (sljit_sw)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - (sljit_sw)(buf_ptr + 2)) >= -0x02000000);
- *buf_ptr |= (((sljit_sw)jump->u.label->addr - (sljit_sw)(buf_ptr + 2)) >> 2) & 0x00ffffff;
+ SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - jump_addr) >= -0x02000000);
+ *buf_ptr |= (((sljit_sw)jump->u.label->addr - jump_addr) >> 2) & 0x00ffffff;
}
else {
- SLJIT_ASSERT(((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) >= -0x02000000);
- *buf_ptr |= (((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) >> 2) & 0x00ffffff;
+ SLJIT_ASSERT(((sljit_sw)jump->u.target - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.target - jump_addr) >= -0x02000000);
+ *buf_ptr |= (((sljit_sw)jump->u.target - jump_addr) >> 2) & 0x00ffffff;
}
}
else if (jump->flags & SLJIT_REWRITABLE_JUMP) {
@@ -747,10 +759,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump->addr = (sljit_uw)code_ptr;
code_ptr[0] = (sljit_uw)buf_ptr;
code_ptr[1] = *buf_ptr;
- inline_set_jump_addr((sljit_uw)code_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
+ inline_set_jump_addr((sljit_uw)code_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
code_ptr += 2;
#else
- inline_set_jump_addr((sljit_uw)buf_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
+ inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
#endif
}
else {
@@ -763,7 +775,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr += 1;
*buf_ptr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
#else
- inline_set_jump_addr((sljit_uw)buf_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
+ inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
#endif
}
jump = jump->next;
@@ -782,7 +794,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
else
buf_ptr += 1;
/* Set the value again (can be a simple constant). */
- inline_set_const((sljit_uw)code_ptr, *buf_ptr, 0);
+ inline_set_const((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0);
code_ptr += 2;
const_ = const_->next;
@@ -792,30 +804,90 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(code_ptr - code <= (sljit_s32)size);
compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_uw);
- SLJIT_ENABLE_EXEC(code, code_ptr);
+
+ code = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
SLJIT_CACHE_FLUSH(code, code_ptr);
return code;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#else
+ /* Available by default. */
+ return 1;
+#endif
+
+ case SLJIT_HAS_PRE_UPDATE:
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_CMOV:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
/* --------------------------------------------------------------------- */
/* Entry, exit */
/* --------------------------------------------------------------------- */
-/* emit_op inp_flags.
- WRITE_BACK must be the first, since it is a flag. */
-#define WRITE_BACK 0x01
-#define ALLOW_IMM 0x02
-#define ALLOW_INV_IMM 0x04
-#define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM)
-#define ARG_TEST 0x08
-
/* Creates an index in data_transfer_insts array. */
#define WORD_DATA 0x00
-#define BYTE_DATA 0x10
-#define HALF_DATA 0x20
-#define SIGNED_DATA 0x40
-#define LOAD_DATA 0x80
+#define BYTE_DATA 0x01
+#define HALF_DATA 0x02
+#define PRELOAD_DATA 0x03
+#define SIGNED_DATA 0x04
+#define LOAD_DATA 0x08
+
+/* emit_op inp_flags.
+ WRITE_BACK must be the first, since it is a flag. */
+#define WRITE_BACK 0x10
+#define ALLOW_IMM 0x20
+#define ALLOW_INV_IMM 0x40
+#define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM)
+
+/* s/l - store/load (1 bit)
+ u/s - signed/unsigned (1 bit)
+ w/b/h/N - word/byte/half/NOT allowed (2 bit)
+ Storing signed and unsigned values are the same operations. */
+
+static const sljit_uw data_transfer_insts[16] = {
+/* s u w */ 0xe5000000 /* str */,
+/* s u b */ 0xe5400000 /* strb */,
+/* s u h */ 0xe10000b0 /* strh */,
+/* s u N */ 0x00000000 /* not allowed */,
+/* s s w */ 0xe5000000 /* str */,
+/* s s b */ 0xe5400000 /* strb */,
+/* s s h */ 0xe10000b0 /* strh */,
+/* s s N */ 0x00000000 /* not allowed */,
+
+/* l u w */ 0xe5100000 /* ldr */,
+/* l u b */ 0xe5500000 /* ldrb */,
+/* l u h */ 0xe11000b0 /* ldrh */,
+/* l u p */ 0xf5500000 /* preload data */,
+/* l s w */ 0xe5100000 /* ldr */,
+/* l s b */ 0xe11000d0 /* ldrsb */,
+/* l s h */ 0xe11000f0 /* ldrsh */,
+/* l s N */ 0x00000000 /* not allowed */,
+};
+
+#define EMIT_DATA_TRANSFER(type, add, wb, target_reg, base_reg, arg) \
+ (data_transfer_insts[(type) & 0xf] | ((add) << 23) | ((wb) << (21 - 4)) | RD(target_reg) | RN(base_reg) | (arg))
+
+/* Normal ldr/str instruction.
+ Type2: ldrsb, ldrh, ldrsh */
+#define IS_TYPE1_TRANSFER(type) \
+ (data_transfer_insts[(type) & 0xf] & 0x04000000)
+#define TYPE2_TRANSFER_IMM(imm) \
+ (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22))
/* Condition: AL. */
#define EMIT_DATA_PROCESS_INS(opcode, set_flags, dst, src1, src2) \
@@ -913,52 +985,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
/* Operators */
/* --------------------------------------------------------------------- */
-/* s/l - store/load (1 bit)
- u/s - signed/unsigned (1 bit)
- w/b/h/N - word/byte/half/NOT allowed (2 bit)
- It contans 16 items, but not all are different. */
-
-static sljit_sw data_transfer_insts[16] = {
-/* s u w */ 0xe5000000 /* str */,
-/* s u b */ 0xe5400000 /* strb */,
-/* s u h */ 0xe10000b0 /* strh */,
-/* s u N */ 0x00000000 /* not allowed */,
-/* s s w */ 0xe5000000 /* str */,
-/* s s b */ 0xe5400000 /* strb */,
-/* s s h */ 0xe10000b0 /* strh */,
-/* s s N */ 0x00000000 /* not allowed */,
-
-/* l u w */ 0xe5100000 /* ldr */,
-/* l u b */ 0xe5500000 /* ldrb */,
-/* l u h */ 0xe11000b0 /* ldrh */,
-/* l u N */ 0x00000000 /* not allowed */,
-/* l s w */ 0xe5100000 /* ldr */,
-/* l s b */ 0xe11000d0 /* ldrsb */,
-/* l s h */ 0xe11000f0 /* ldrsh */,
-/* l s N */ 0x00000000 /* not allowed */,
-};
-
-#define EMIT_DATA_TRANSFER(type, add, wb, target, base1, base2) \
- (data_transfer_insts[(type) >> 4] | ((add) << 23) | ((wb) << 21) | (reg_map[target] << 12) | (reg_map[base1] << 16) | (base2))
-/* Normal ldr/str instruction.
- Type2: ldrsb, ldrh, ldrsh */
-#define IS_TYPE1_TRANSFER(type) \
- (data_transfer_insts[(type) >> 4] & 0x04000000)
-#define TYPE2_TRANSFER_IMM(imm) \
- (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22))
-
/* flags: */
/* Arguments are swapped. */
#define ARGS_SWAPPED 0x01
/* Inverted immediate. */
#define INV_IMM 0x02
/* Source and destination is register. */
-#define REG_DEST 0x04
-#define REG_SOURCE 0x08
- /* One instruction is enough. */
-#define FAST_DEST 0x10
- /* Multiple instructions are required. */
-#define SLOW_DEST 0x20
+#define MOVE_REG_CONV 0x04
+ /* Unused return value. */
+#define UNUSED_RETURN 0x08
/* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */
#define SET_FLAGS (1 << 20)
/* dst: reg
@@ -967,157 +1002,135 @@ static sljit_sw data_transfer_insts[16] = {
SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */
#define SRC2_IMM (1 << 25)
-#define EMIT_DATA_PROCESS_INS_AND_RETURN(opcode) \
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)))
-
-#define EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(opcode, dst, src1, src2) \
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, src2))
-
#define EMIT_SHIFT_INS_AND_RETURN(opcode) \
SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \
if (compiler->shift_imm != 0x20) { \
SLJIT_ASSERT(src1 == TMP_REG1); \
SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \
+ \
if (compiler->shift_imm != 0) \
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | reg_map[src2])); \
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, reg_map[src2])); \
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, \
+ dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | RM(src2))); \
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, RM(src2))); \
} \
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | ((flags & ARGS_SWAPPED) ? reg_map[src2] : reg_map[src1])));
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, \
+ dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | RM((flags & ARGS_SWAPPED) ? src2 : src1)));
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
{
- sljit_sw mul_inst;
-
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
if (dst != src2) {
if (src2 & SRC2_IMM) {
- if (flags & INV_IMM)
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS((flags & INV_IMM) ? MVN_DP : MOV_DP, 0,
+ dst, SLJIT_UNUSED, src2));
}
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, reg_map[src2]);
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(src2)));
}
return SLJIT_SUCCESS;
case SLJIT_MOV_U8:
case SLJIT_MOV_S8:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
- if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
+ if (flags & MOVE_REG_CONV) {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
if (op == SLJIT_MOV_U8)
return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff));
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2])));
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_U8 ? 0x20 : 0x40) | reg_map[dst]));
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | RM(src2))));
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_U8 ? 0x20 : 0x40) | RM(dst)));
#else
return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2));
#endif
}
else if (dst != src2) {
SLJIT_ASSERT(src2 & SRC2_IMM);
- if (flags & INV_IMM)
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS((flags & INV_IMM) ? MVN_DP : MOV_DP, 0,
+ dst, SLJIT_UNUSED, src2));
}
return SLJIT_SUCCESS;
case SLJIT_MOV_U16:
case SLJIT_MOV_S16:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
- if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
+ if (flags & MOVE_REG_CONV) {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2])));
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_U16 ? 0x20 : 0x40) | reg_map[dst]));
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | RM(src2))));
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_U16 ? 0x20 : 0x40) | RM(dst)));
#else
return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2));
#endif
}
else if (dst != src2) {
SLJIT_ASSERT(src2 & SRC2_IMM);
- if (flags & INV_IMM)
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS((flags & INV_IMM) ? MVN_DP : MOV_DP, 0,
+ dst, SLJIT_UNUSED, src2));
}
return SLJIT_SUCCESS;
case SLJIT_NOT:
if (src2 & SRC2_IMM) {
- if (flags & INV_IMM)
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS((flags & INV_IMM) ? MOV_DP : MVN_DP, flags & SET_FLAGS,
+ dst, SLJIT_UNUSED, src2));
}
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, RM(src2));
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MVN_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, RM(src2)));
case SLJIT_CLZ:
SLJIT_ASSERT(!(flags & INV_IMM));
SLJIT_ASSERT(!(src2 & SRC2_IMM));
FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
- if (flags & SET_FLAGS)
- EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(CMP_DP, SLJIT_UNUSED, dst, SRC2_IMM);
return SLJIT_SUCCESS;
case SLJIT_ADD:
SLJIT_ASSERT(!(flags & INV_IMM));
- EMIT_DATA_PROCESS_INS_AND_RETURN(ADD_DP);
+ if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMN_DP, SET_FLAGS,
+ SLJIT_UNUSED, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, flags & SET_FLAGS,
+ dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
case SLJIT_ADDC:
SLJIT_ASSERT(!(flags & INV_IMM));
- EMIT_DATA_PROCESS_INS_AND_RETURN(ADC_DP);
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(ADC_DP, flags & SET_FLAGS,
+ dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
case SLJIT_SUB:
SLJIT_ASSERT(!(flags & INV_IMM));
- if (!(flags & ARGS_SWAPPED))
- EMIT_DATA_PROCESS_INS_AND_RETURN(SUB_DP);
- EMIT_DATA_PROCESS_INS_AND_RETURN(RSB_DP);
+ if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS,
+ SLJIT_UNUSED, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(!(flags & ARGS_SWAPPED) ? SUB_DP : RSB_DP, flags & SET_FLAGS,
+ dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
case SLJIT_SUBC:
SLJIT_ASSERT(!(flags & INV_IMM));
- if (!(flags & ARGS_SWAPPED))
- EMIT_DATA_PROCESS_INS_AND_RETURN(SBC_DP);
- EMIT_DATA_PROCESS_INS_AND_RETURN(RSC_DP);
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(!(flags & ARGS_SWAPPED) ? SBC_DP : RSC_DP, flags & SET_FLAGS,
+ dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
case SLJIT_MUL:
SLJIT_ASSERT(!(flags & INV_IMM));
SLJIT_ASSERT(!(src2 & SRC2_IMM));
- if (SLJIT_UNLIKELY(op & SLJIT_SET_O))
- mul_inst = SMULL | (reg_map[TMP_REG3] << 16) | (reg_map[dst] << 12);
- else
- mul_inst = MUL | (reg_map[dst] << 16);
- if (dst != src2)
- FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src1] << 8) | reg_map[src2]));
- else if (dst != src1)
- FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[src1]));
- else {
- /* Rm and Rd must not be the same register. */
- SLJIT_ASSERT(dst != TMP_REG1);
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, reg_map[src2])));
- FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[TMP_REG1]));
- }
+ if (!HAS_FLAGS(op))
+ return push_inst(compiler, MUL | (reg_map[dst] << 16) | (reg_map[src2] << 8) | reg_map[src1]);
- if (!(op & SLJIT_SET_O))
- return SLJIT_SUCCESS;
+ FAIL_IF(push_inst(compiler, SMULL | (reg_map[TMP_REG1] << 16) | (reg_map[dst] << 12) | (reg_map[src2] << 8) | reg_map[src1]));
- /* We need to use TMP_REG3. */
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- /* cmp TMP_REG2, dst asr #31. */
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS, SLJIT_UNUSED, TMP_REG3, RM(dst) | 0xfc0));
+ /* cmp TMP_REG1, dst asr #31. */
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS, SLJIT_UNUSED, TMP_REG1, RM(dst) | 0xfc0));
case SLJIT_AND:
- if (!(flags & INV_IMM))
- EMIT_DATA_PROCESS_INS_AND_RETURN(AND_DP);
- EMIT_DATA_PROCESS_INS_AND_RETURN(BIC_DP);
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(!(flags & INV_IMM) ? AND_DP : BIC_DP, flags & SET_FLAGS,
+ dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
case SLJIT_OR:
SLJIT_ASSERT(!(flags & INV_IMM));
- EMIT_DATA_PROCESS_INS_AND_RETURN(ORR_DP);
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(ORR_DP, flags & SET_FLAGS, dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
case SLJIT_XOR:
SLJIT_ASSERT(!(flags & INV_IMM));
- EMIT_DATA_PROCESS_INS_AND_RETURN(EOR_DP);
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(EOR_DP, flags & SET_FLAGS, dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
case SLJIT_SHL:
EMIT_SHIFT_INS_AND_RETURN(0);
@@ -1128,12 +1141,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
case SLJIT_ASHR:
EMIT_SHIFT_INS_AND_RETURN(2);
}
- SLJIT_ASSERT_STOP();
+
+ SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
}
-#undef EMIT_DATA_PROCESS_INS_AND_RETURN
-#undef EMIT_FULL_DATA_PROCESS_INS_AND_RETURN
#undef EMIT_SHIFT_INS_AND_RETURN
/* Tests whether the immediate can be stored in the 12 bit imm field.
@@ -1313,291 +1325,116 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg,
/* Load integer. */
return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), imm);
#else
- return emit_imm(compiler, reg, imm);
+ FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
+ if (imm <= 0xffff)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));
#endif
}
-/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
-static sljit_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 reg, sljit_sw value)
+static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
{
- if (value >= 0) {
- value = get_imm(value);
- if (value)
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, dst, reg, value));
- }
- else {
- value = get_imm(-value);
- if (value)
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, dst, reg, value));
- }
- return SLJIT_ERR_UNSUPPORTED;
-}
+ sljit_uw offset_reg, imm;
+ sljit_uw is_type1_transfer = IS_TYPE1_TRANSFER(flags);
-/* Can perform an operation using at most 1 instruction. */
-static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
-{
- sljit_uw imm;
+ SLJIT_ASSERT (arg & SLJIT_MEM);
+ SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
- if (arg & SLJIT_IMM) {
- imm = get_imm(argw);
- if (imm) {
- if (inp_flags & ARG_TEST)
- return 1;
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, imm)));
- return -1;
- }
- imm = get_imm(~argw);
- if (imm) {
- if (inp_flags & ARG_TEST)
- return 1;
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, imm)));
- return -1;
- }
- return 0;
- }
-
- SLJIT_ASSERT(arg & SLJIT_MEM);
-
- /* Fast loads/stores. */
- if (!(arg & REG_MASK))
- return 0;
-
- if (arg & OFFS_REG_MASK) {
- if ((argw & 0x3) != 0 && !IS_TYPE1_TRANSFER(inp_flags))
- return 0;
-
- if (inp_flags & ARG_TEST)
- return 1;
- FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK,
- RM(OFFS_REG(arg)) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7))));
- return -1;
- }
-
- if (IS_TYPE1_TRANSFER(inp_flags)) {
- if (argw >= 0 && argw <= 0xfff) {
- if (inp_flags & ARG_TEST)
- return 1;
- FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, argw)));
- return -1;
- }
- if (argw < 0 && argw >= -0xfff) {
- if (inp_flags & ARG_TEST)
- return 1;
- FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, -argw)));
- return -1;
- }
- }
- else {
- if (argw >= 0 && argw <= 0xff) {
- if (inp_flags & ARG_TEST)
- return 1;
- FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw))));
- return -1;
- }
- if (argw < 0 && argw >= -0xff) {
- if (inp_flags & ARG_TEST)
- return 1;
- argw = -argw;
- FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw))));
- return -1;
- }
- }
-
- return 0;
-}
-
-/* See getput_arg below.
- Note: can_cache is called only for binary operators. Those
- operators always uses word arguments without write back. */
-static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
-{
- /* Immediate caching is not supported as it would be an operation on constant arguments. */
- if (arg & SLJIT_IMM)
- return 0;
-
- /* Always a simple operation. */
- if (arg & OFFS_REG_MASK)
- return 0;
-
- if (!(arg & REG_MASK)) {
- /* Immediate access. */
- if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff))
- return 1;
- return 0;
- }
-
- if (argw <= 0xfffff && argw >= -0xfffff)
- return 0;
-
- if (argw == next_argw && (next_arg & SLJIT_MEM))
- return 1;
-
- if (arg == next_arg && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff))
- return 1;
-
- return 0;
-}
-
-#define GETPUT_ARG_DATA_TRANSFER(add, wb, target, base, imm) \
- if (max_delta & 0xf00) \
- FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, imm))); \
- else \
- FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, TYPE2_TRANSFER_IMM(imm))));
-
-#define TEST_WRITE_BACK() \
- if (inp_flags & WRITE_BACK) { \
- tmp_r = arg & REG_MASK; \
- if (reg == tmp_r) { \
- /* This can only happen for stores */ \
- /* since ldr reg, [reg, ...]! has no meaning */ \
- SLJIT_ASSERT(!(inp_flags & LOAD_DATA)); \
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(reg)))); \
- reg = TMP_REG3; \
- } \
- }
-
-/* Emit the necessary instructions. See can_cache above. */
-static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
-{
- sljit_s32 tmp_r;
- sljit_sw max_delta;
- sljit_sw sign;
- sljit_uw imm;
-
- if (arg & SLJIT_IMM) {
- SLJIT_ASSERT(inp_flags & LOAD_DATA);
- return load_immediate(compiler, reg, argw);
- }
-
- SLJIT_ASSERT(arg & SLJIT_MEM);
-
- tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3;
- max_delta = IS_TYPE1_TRANSFER(inp_flags) ? 0xfff : 0xff;
+ SLJIT_COMPILE_ASSERT(WRITE_BACK == 0x10, optimized_for_emit_data_transfer);
if ((arg & REG_MASK) == SLJIT_UNUSED) {
/* Write back is not used. */
- imm = (sljit_uw)(argw - compiler->cache_argw);
- if ((compiler->cache_arg & SLJIT_IMM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
- if (imm <= (sljit_uw)max_delta) {
- sign = 1;
- argw = argw - compiler->cache_argw;
- }
- else {
- sign = 0;
- argw = compiler->cache_argw - argw;
- }
-
- GETPUT_ARG_DATA_TRANSFER(sign, 0, reg, TMP_REG3, argw);
- return SLJIT_SUCCESS;
+ if (is_type1_transfer) {
+ FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xfff));
+ argw &= 0xfff;
+ }
+ else {
+ FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xff));
+ argw &= 0xff;
}
- /* With write back, we can create some sophisticated loads, but
- it is hard to decide whether we should convert downward (0s) or upward (1s). */
- imm = (sljit_uw)(argw - next_argw);
- if ((next_arg & SLJIT_MEM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
- SLJIT_ASSERT(inp_flags & LOAD_DATA);
-
- compiler->cache_arg = SLJIT_IMM;
- compiler->cache_argw = argw;
- tmp_r = TMP_REG3;
- }
-
- FAIL_IF(load_immediate(compiler, tmp_r, argw));
- GETPUT_ARG_DATA_TRANSFER(1, 0, reg, tmp_r, 0);
- return SLJIT_SUCCESS;
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, 0, reg, tmp_reg, is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw)));
}
if (arg & OFFS_REG_MASK) {
- SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00));
- if (inp_flags & WRITE_BACK)
- tmp_r = arg & REG_MASK;
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7))));
- return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, 0, reg, tmp_r, TYPE2_TRANSFER_IMM(0)));
+ offset_reg = OFFS_REG(arg);
+ arg &= REG_MASK;
+ argw &= 0x3;
+
+ if (argw != 0 && !is_type1_transfer) {
+ SLJIT_ASSERT(!(flags & WRITE_BACK));
+
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_reg, arg, RM(offset_reg) | (argw << 7))));
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, 0, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));
+ }
+
+ /* Bit 25: RM is offset. */
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg,
+ RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | (argw << 7)));
}
- imm = (sljit_uw)(argw - compiler->cache_argw);
- if (compiler->cache_arg == arg && imm <= (sljit_uw)max_delta) {
- SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
- GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, imm);
- return SLJIT_SUCCESS;
+ arg &= REG_MASK;
+
+ if (is_type1_transfer) {
+ if (argw > 0xfff) {
+ imm = get_imm(argw & ~0xfff);
+ if (imm) {
+ offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, offset_reg, arg, imm)));
+ argw = argw & 0xfff;
+ arg = offset_reg;
+ }
+ }
+ else if (argw < -0xfff) {
+ imm = get_imm(-argw & ~0xfff);
+ if (imm) {
+ offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, offset_reg, arg, imm)));
+ argw = -(-argw & 0xfff);
+ arg = offset_reg;
+ }
+ }
+
+ if (argw >= 0 && argw <= 0xfff) {
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg & REG_MASK, argw));
+ }
+ if (argw < 0 && argw >= -0xfff) {
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, flags & WRITE_BACK, reg, arg & REG_MASK, -argw));
+ }
}
- if (compiler->cache_arg == arg && imm >= (sljit_uw)-max_delta) {
- SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
- imm = (sljit_uw)-(sljit_sw)imm;
- GETPUT_ARG_DATA_TRANSFER(0, 0, reg, TMP_REG3, imm);
- return SLJIT_SUCCESS;
+ else {
+ if (argw > 0xff) {
+ imm = get_imm(argw & ~0xff);
+ if (imm) {
+ offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, offset_reg, arg, imm)));
+ argw = argw & 0xff;
+ arg = offset_reg;
+ }
+ }
+ else if (argw < -0xff) {
+ imm = get_imm(-argw & ~0xff);
+ if (imm) {
+ offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, offset_reg, arg, imm)));
+ argw = -(-argw & 0xff);
+ arg = offset_reg;
+ }
+ }
+
+ if (argw >= 0 && argw <= 0xff) {
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg, TYPE2_TRANSFER_IMM(argw)));
+ }
+ if (argw < 0 && argw >= -0xff) {
+ argw = -argw;
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, flags & WRITE_BACK, reg, arg, TYPE2_TRANSFER_IMM(argw)));
+ }
}
- imm = get_imm(argw & ~max_delta);
- if (imm) {
- TEST_WRITE_BACK();
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, imm)));
- GETPUT_ARG_DATA_TRANSFER(1, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
- return SLJIT_SUCCESS;
- }
-
- imm = get_imm(-argw & ~max_delta);
- if (imm) {
- argw = -argw;
- TEST_WRITE_BACK();
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & REG_MASK, imm)));
- GETPUT_ARG_DATA_TRANSFER(0, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
- return SLJIT_SUCCESS;
- }
-
- if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) {
- TEST_WRITE_BACK();
- return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
- }
-
- if (argw == next_argw && (next_arg & SLJIT_MEM)) {
- SLJIT_ASSERT(inp_flags & LOAD_DATA);
- FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
-
- compiler->cache_arg = SLJIT_IMM;
- compiler->cache_argw = argw;
-
- TEST_WRITE_BACK();
- return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
- }
-
- imm = (sljit_uw)(argw - next_argw);
- if (arg == next_arg && !(inp_flags & WRITE_BACK) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
- SLJIT_ASSERT(inp_flags & LOAD_DATA);
- FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & REG_MASK])));
-
- compiler->cache_arg = arg;
- compiler->cache_argw = argw;
-
- GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, 0);
- return SLJIT_SUCCESS;
- }
-
- if ((arg & REG_MASK) == tmp_r) {
- compiler->cache_arg = SLJIT_IMM;
- compiler->cache_argw = argw;
- tmp_r = TMP_REG3;
- }
-
- FAIL_IF(load_immediate(compiler, tmp_r, argw));
- return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0)));
-}
-
-static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
-{
- if (getput_arg_fast(compiler, flags, reg, arg, argw))
- return compiler->error;
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
-}
-
-static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
-{
- if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
- return compiler->error;
- return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+ FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg,
+ RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0)));
}
static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
@@ -1605,68 +1442,66 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- /* arg1 goes to TMP_REG1 or src reg
- arg2 goes to TMP_REG2, imm or src reg
- TMP_REG3 can be used for caching
- result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
+ /* src1 is reg or TMP_REG1
+ src2 is reg, TMP_REG2, or imm
+ result goes to TMP_REG2, so put result can use TMP_REG1. */
/* We prefers register and simple consts. */
- sljit_s32 dst_r;
- sljit_s32 src1_r;
- sljit_s32 src2_r = 0;
- sljit_s32 sugg_src2_r = TMP_REG2;
- sljit_s32 flags = GET_FLAGS(op) ? SET_FLAGS : 0;
-
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
+ sljit_s32 dst_reg;
+ sljit_s32 src1_reg;
+ sljit_s32 src2_reg;
+ sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
/* Destination check. */
- if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
- if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM))
- return SLJIT_SUCCESS;
- dst_r = TMP_REG2;
- }
- else if (FAST_IS_REG(dst)) {
- dst_r = dst;
- flags |= REG_DEST;
- if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
- sugg_src2_r = dst_r;
- }
- else {
- SLJIT_ASSERT(dst & SLJIT_MEM);
- if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) {
- flags |= FAST_DEST;
- dst_r = TMP_REG2;
- }
- else {
- flags |= SLOW_DEST;
- dst_r = 0;
- }
- }
+ if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED))
+ flags |= UNUSED_RETURN;
- /* Source 1. */
- if (FAST_IS_REG(src1))
- src1_r = src1;
- else if (FAST_IS_REG(src2)) {
- flags |= ARGS_SWAPPED;
- src1_r = src2;
- src2 = src1;
- src2w = src1w;
- }
- else do { /* do { } while(0) is used because of breaks. */
- src1_r = 0;
- if ((inp_flags & ALLOW_ANY_IMM) && (src1 & SLJIT_IMM)) {
- /* The second check will generate a hit. */
- src2_r = get_imm(src1w);
- if (src2_r) {
+ SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM));
+
+ src2_reg = 0;
+
+ do {
+ if (!(inp_flags & ALLOW_IMM))
+ break;
+
+ if (src2 & SLJIT_IMM) {
+ src2_reg = get_imm(src2w);
+ if (src2_reg)
+ break;
+ if (inp_flags & ALLOW_INV_IMM) {
+ src2_reg = get_imm(~src2w);
+ if (src2_reg) {
+ flags |= INV_IMM;
+ break;
+ }
+ }
+ if (GET_OPCODE(op) == SLJIT_ADD) {
+ src2_reg = get_imm(-src2w);
+ if (src2_reg) {
+ op = SLJIT_SUB | GET_ALL_FLAGS(op);
+ break;
+ }
+ }
+ if (GET_OPCODE(op) == SLJIT_SUB) {
+ src2_reg = get_imm(-src2w);
+ if (src2_reg) {
+ op = SLJIT_ADD | GET_ALL_FLAGS(op);
+ break;
+ }
+ }
+ }
+
+ if (src1 & SLJIT_IMM) {
+ src2_reg = get_imm(src1w);
+ if (src2_reg) {
flags |= ARGS_SWAPPED;
src1 = src2;
src1w = src2w;
break;
}
if (inp_flags & ALLOW_INV_IMM) {
- src2_r = get_imm(~src1w);
- if (src2_r) {
+ src2_reg = get_imm(~src1w);
+ if (src2_reg) {
flags |= ARGS_SWAPPED | INV_IMM;
src1 = src2;
src1w = src2w;
@@ -1674,9 +1509,9 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
}
}
if (GET_OPCODE(op) == SLJIT_ADD) {
- src2_r = get_imm(-src1w);
- if (src2_r) {
- /* Note: ARGS_SWAPPED is intentionally not applied! */
+ src2_reg = get_imm(-src1w);
+ if (src2_reg) {
+ /* Note: add is commutative operation. */
src1 = src2;
src1w = src2w;
op = SLJIT_SUB | GET_ALL_FLAGS(op);
@@ -1684,110 +1519,54 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
}
}
}
+ } while(0);
- if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w)) {
- FAIL_IF(compiler->error);
- src1_r = TMP_REG1;
+ /* Source 1. */
+ if (FAST_IS_REG(src1))
+ src1_reg = src1;
+ else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
+ src1_reg = TMP_REG1;
+ }
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1_reg = TMP_REG1;
+ }
+
+ /* Destination. */
+ dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op <= SLJIT_MOVU_P) {
+ if (dst & SLJIT_MEM) {
+ if (inp_flags & BYTE_DATA)
+ inp_flags &= ~SIGNED_DATA;
+
+ if (FAST_IS_REG(src2))
+ return emit_op_mem(compiler, inp_flags, src2, dst, dstw, TMP_REG2);
}
- } while (0);
+
+ if (FAST_IS_REG(src2) && dst_reg != TMP_REG2)
+ flags |= MOVE_REG_CONV;
+ }
/* Source 2. */
- if (src2_r == 0) {
- if (FAST_IS_REG(src2)) {
- src2_r = src2;
- flags |= REG_SOURCE;
- if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
- dst_r = src2_r;
- }
- else do { /* do { } while(0) is used because of breaks. */
- if ((inp_flags & ALLOW_ANY_IMM) && (src2 & SLJIT_IMM)) {
- src2_r = get_imm(src2w);
- if (src2_r)
- break;
- if (inp_flags & ALLOW_INV_IMM) {
- src2_r = get_imm(~src2w);
- if (src2_r) {
- flags |= INV_IMM;
- break;
- }
- }
- if (GET_OPCODE(op) == SLJIT_ADD) {
- src2_r = get_imm(-src2w);
- if (src2_r) {
- op = SLJIT_SUB | GET_ALL_FLAGS(op);
- flags &= ~ARGS_SWAPPED;
- break;
- }
- }
- if (GET_OPCODE(op) == SLJIT_SUB && !(flags & ARGS_SWAPPED)) {
- src2_r = get_imm(-src2w);
- if (src2_r) {
- op = SLJIT_ADD | GET_ALL_FLAGS(op);
- flags &= ~ARGS_SWAPPED;
- break;
- }
- }
- }
+ if (src2_reg == 0) {
+ src2_reg = (op <= SLJIT_MOVU_P) ? dst_reg : TMP_REG2;
- /* src2_r is 0. */
- if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) {
- FAIL_IF(compiler->error);
- src2_r = sugg_src2_r;
- }
- } while (0);
- }
-
- /* src1_r, src2_r and dst_r can be zero (=unprocessed) or non-zero.
- If they are zero, they must not be registers. */
- if (src1_r == 0 && src2_r == 0 && dst_r == 0) {
- if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
- SLJIT_ASSERT(!(flags & ARGS_SWAPPED));
- flags |= ARGS_SWAPPED;
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src2, src2w, src1, src1w));
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src1, src1w, dst, dstw));
- }
- else {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
- }
- src1_r = TMP_REG1;
- src2_r = TMP_REG2;
- }
- else if (src1_r == 0 && src2_r == 0) {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
- src1_r = TMP_REG1;
- }
- else if (src1_r == 0 && dst_r == 0) {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
- src1_r = TMP_REG1;
- }
- else if (src2_r == 0 && dst_r == 0) {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
- src2_r = sugg_src2_r;
- }
-
- if (dst_r == 0)
- dst_r = TMP_REG2;
-
- if (src1_r == 0) {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0));
- src1_r = TMP_REG1;
- }
-
- if (src2_r == 0) {
- FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0));
- src2_r = sugg_src2_r;
- }
-
- FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
-
- if (flags & (FAST_DEST | SLOW_DEST)) {
- if (flags & FAST_DEST)
- FAIL_IF(getput_arg_fast(compiler, inp_flags, dst_r, dst, dstw));
+ if (FAST_IS_REG(src2))
+ src2_reg = src2;
+ else if (src2 & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, src2_reg, src2, src2w, TMP_REG2));
else
- FAIL_IF(getput_arg(compiler, inp_flags, dst_r, dst, dstw, 0, 0));
+ FAIL_IF(load_immediate(compiler, src2_reg, src2w));
}
- return SLJIT_SUCCESS;
+
+ FAIL_IF(emit_single_op(compiler, op, flags, dst_reg, src1_reg, src2_reg));
+
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+
+ return emit_op_mem(compiler, inp_flags, dst_reg, dst, dstw, TMP_REG1);
}
#ifdef __cplusplus
@@ -1807,6 +1586,9 @@ extern int __aeabi_idivmod(int numerator, int denominator);
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
+ sljit_sw saved_reg_list[3];
+ sljit_sw saved_reg_count;
+
CHECK_ERROR();
CHECK(check_sljit_emit_op0(compiler, op));
@@ -1820,33 +1602,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
break;
case SLJIT_LMUL_UW:
case SLJIT_LMUL_SW:
-#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)
| (reg_map[SLJIT_R1] << 16)
| (reg_map[SLJIT_R0] << 12)
| (reg_map[SLJIT_R0] << 8)
| reg_map[SLJIT_R1]);
-#else
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_R1))));
- return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)
- | (reg_map[SLJIT_R1] << 16)
- | (reg_map[SLJIT_R0] << 12)
- | (reg_map[SLJIT_R0] << 8)
- | reg_map[TMP_REG1]);
-#endif
case SLJIT_DIVMOD_UW:
case SLJIT_DIVMOD_SW:
case SLJIT_DIV_UW:
case SLJIT_DIV_SW:
SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
- SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2, bad_register_mapping);
+ SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3);
- if ((op >= SLJIT_DIV_UW) && (compiler->scratches >= 3)) {
- FAIL_IF(push_inst(compiler, 0xe52d2008 /* str r2, [sp, #-8]! */));
- FAIL_IF(push_inst(compiler, 0xe58d1004 /* str r1, [sp, #4] */));
+ saved_reg_count = 0;
+ if (compiler->scratches >= 4)
+ saved_reg_list[saved_reg_count++] = 3;
+ if (compiler->scratches >= 3)
+ saved_reg_list[saved_reg_count++] = 2;
+ if (op >= SLJIT_DIV_UW)
+ saved_reg_list[saved_reg_count++] = 1;
+
+ if (saved_reg_count > 0) {
+ FAIL_IF(push_inst(compiler, 0xe52d0000 | (saved_reg_count >= 3 ? 16 : 8)
+ | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
+ if (saved_reg_count >= 2) {
+ SLJIT_ASSERT(saved_reg_list[1] < 8);
+ FAIL_IF(push_inst(compiler, 0xe58d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */));
+ }
+ if (saved_reg_count >= 3) {
+ SLJIT_ASSERT(saved_reg_list[2] < 8);
+ FAIL_IF(push_inst(compiler, 0xe58d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */));
+ }
}
- else if ((op >= SLJIT_DIV_UW) || (compiler->scratches >= 3))
- FAIL_IF(push_inst(compiler, 0xe52d0008 | (op >= SLJIT_DIV_UW ? 0x1000 : 0x2000) /* str r1/r2, [sp, #-8]! */));
#if defined(__GNUC__)
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
@@ -1855,12 +1642,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
#error "Software divmod functions are needed"
#endif
- if ((op >= SLJIT_DIV_UW) && (compiler->scratches >= 3)) {
- FAIL_IF(push_inst(compiler, 0xe59d1004 /* ldr r1, [sp, #4] */));
- FAIL_IF(push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */));
+ if (saved_reg_count > 0) {
+ if (saved_reg_count >= 3) {
+ SLJIT_ASSERT(saved_reg_list[2] < 8);
+ FAIL_IF(push_inst(compiler, 0xe59d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */));
+ }
+ if (saved_reg_count >= 2) {
+ SLJIT_ASSERT(saved_reg_list[1] < 8);
+ FAIL_IF(push_inst(compiler, 0xe59d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));
+ }
+ return push_inst(compiler, 0xe49d0000 | (saved_reg_count >= 3 ? 16 : 8)
+ | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
}
- else if ((op >= SLJIT_DIV_UW) || (compiler->scratches >= 3))
- return push_inst(compiler, 0xe49d0008 | (op >= SLJIT_DIV_UW ? 0x1000 : 0x2000) /* ldr r1/r2, [sp], #8 */);
return SLJIT_SUCCESS;
}
@@ -1876,6 +1669,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+ if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
+ return emit_op_mem(compiler, PRELOAD_DATA | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);
+#endif
+ return SLJIT_SUCCESS;
+ }
+
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
case SLJIT_MOV_U32:
@@ -1941,6 +1742,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+ return SLJIT_SUCCESS;
+
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
case SLJIT_ADDC:
@@ -1997,43 +1801,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
-
-/* 0 - no fpu
- 1 - vfp */
-static sljit_s32 arm_fpu_type = -1;
-
-static void init_compiler(void)
-{
- if (arm_fpu_type != -1)
- return;
-
- /* TODO: Only the OS can help to determine the correct fpu type. */
- arm_fpu_type = 1;
-}
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
- return SLJIT_IS_FPU_AVAILABLE;
-#else
- if (arm_fpu_type == -1)
- init_compiler();
- return arm_fpu_type;
-#endif
-}
-
-#else
-
-#define arm_fpu_type 1
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
-{
- /* Always available. */
- return 1;
-}
-
-#endif
#define FPU_LOAD (1 << 20)
#define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \
@@ -2043,72 +1810,54 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
{
- sljit_sw tmp;
sljit_uw imm;
sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD));
+
SLJIT_ASSERT(arg & SLJIT_MEM);
+ arg &= ~SLJIT_MEM;
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7))));
- arg = SLJIT_MEM | TMP_REG1;
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG2, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7))));
+ arg = TMP_REG2;
argw = 0;
}
/* Fast loads and stores. */
- if ((arg & REG_MASK)) {
+ if (arg) {
if (!(argw & ~0x3fc))
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & REG_MASK, reg, argw >> 2));
if (!(-argw & ~0x3fc))
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & REG_MASK, reg, (-argw) >> 2));
- }
- if (compiler->cache_arg == arg) {
- tmp = argw - compiler->cache_argw;
- if (!(tmp & ~0x3fc))
- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, tmp >> 2));
- if (!(-tmp & ~0x3fc))
- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG3, reg, -tmp >> 2));
- if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, tmp) != SLJIT_ERR_UNSUPPORTED) {
- FAIL_IF(compiler->error);
- compiler->cache_argw = argw;
- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, 0));
- }
- }
-
- if (arg & REG_MASK) {
- if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {
- FAIL_IF(compiler->error);
- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, 0));
- }
imm = get_imm(argw & ~0x3fc);
if (imm) {
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, imm)));
- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, (argw & 0x3fc) >> 2));
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG2, arg & REG_MASK, imm)));
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, (argw & 0x3fc) >> 2));
}
imm = get_imm(-argw & ~0x3fc);
if (imm) {
argw = -argw;
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & REG_MASK, imm)));
- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG1, reg, (argw & 0x3fc) >> 2));
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG2, arg & REG_MASK, imm)));
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG2, reg, (argw & 0x3fc) >> 2));
}
}
- compiler->cache_arg = arg;
- compiler->cache_argw = argw;
- if (arg & REG_MASK) {
- FAIL_IF(load_immediate(compiler, TMP_REG1, argw));
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & REG_MASK, reg_map[TMP_REG1])));
+ if (arg) {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, argw));
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG2, arg & REG_MASK, RM(TMP_REG2))));
}
else
- FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+ FAIL_IF(load_immediate(compiler, TMP_REG2, argw));
- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, 0));
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, 0));
}
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
+ op ^= SLJIT_F32_OP;
+
if (src & SLJIT_MEM) {
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw));
src = TMP_FREG1;
@@ -2116,9 +1865,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_F32_OP, TMP_FREG1, src, 0)));
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
if (FAST_IS_REG(dst))
return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | (TMP_FREG1 << 16));
@@ -2132,6 +1878,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
{
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+ op ^= SLJIT_F32_OP;
+
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, VMOV | RD(src) | (TMP_FREG1 << 16)));
else if (src & SLJIT_MEM) {
@@ -2154,6 +1902,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
+ op ^= SLJIT_F32_OP;
+
if (src1 & SLJIT_MEM) {
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));
src1 = TMP_FREG1;
@@ -2175,16 +1925,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
sljit_s32 dst_r;
CHECK_ERROR();
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
- op ^= SLJIT_F32_OP;
SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error);
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+ if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
+ op ^= SLJIT_F32_OP;
+
if (src & SLJIT_MEM) {
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw));
src = dst_r;
@@ -2229,8 +1978,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
op ^= SLJIT_F32_OP;
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
@@ -2283,21 +2030,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
- /* For UNUSED dst. Uncommon, but possible. */
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
+ SLJIT_ASSERT(reg_map[TMP_REG1] == 14);
if (FAST_IS_REG(dst))
- return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG3)));
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG1)));
/* Memory. */
- if (getput_arg_fast(compiler, WORD_DATA, TMP_REG3, dst, dstw))
- return compiler->error;
- /* TMP_REG3 is used for caching. */
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3))));
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- return getput_arg(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);
+ return emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
@@ -2306,21 +2045,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
+ SLJIT_ASSERT(reg_map[TMP_REG1] == 14);
+
if (FAST_IS_REG(src))
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src))));
- else if (src & SLJIT_MEM) {
- if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw))
- FAIL_IF(compiler->error);
- else {
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- FAIL_IF(getput_arg(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, 0, 0));
- FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(TMP_REG2))));
- }
- }
+ FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, 0, RM(src))));
+ else if (src & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG2));
else if (src & SLJIT_IMM)
- FAIL_IF(load_immediate(compiler, TMP_REG3, srcw));
- return push_inst(compiler, BLX | RM(TMP_REG3));
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+
+ return push_inst(compiler, BX | RM(TMP_REG1));
}
/* --------------------------------------------------------------------- */
@@ -2403,7 +2137,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
struct sljit_jump *jump;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
CHECK_PTR(check_sljit_emit_jump(compiler, type));
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -2416,7 +2149,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
if (type >= SLJIT_FAST_CALL)
PTR_FAIL_IF(prepare_blx(compiler));
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0,
- type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0));
+ type <= SLJIT_JUMP ? TMP_PC : TMP_REG2, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0));
if (jump->flags & SLJIT_REWRITABLE_JUMP) {
jump->addr = compiler->size;
@@ -2433,8 +2166,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
#else
if (type >= SLJIT_FAST_CALL)
jump->flags |= IS_BL;
- PTR_FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
- PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(type)));
+ PTR_FAIL_IF(emit_imm(compiler, TMP_REG2, 0));
+ PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2)) & ~COND_MASK) | get_cc(type)));
jump->addr = compiler->size;
#endif
return jump;
@@ -2454,7 +2187,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));
SLJIT_ASSERT(src & SLJIT_MEM);
- FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw));
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG2));
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2));
}
@@ -2466,12 +2199,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
if (type >= SLJIT_FAST_CALL)
FAIL_IF(prepare_blx(compiler));
- FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
+ FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG2, TMP_PC, 0), 0));
if (type >= SLJIT_FAST_CALL)
FAIL_IF(emit_blx(compiler));
#else
- FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
- FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));
+ FAIL_IF(emit_imm(compiler, TMP_REG2, 0));
+ FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2)));
#endif
jump->addr = compiler->size;
return SLJIT_SUCCESS;
@@ -2479,55 +2212,80 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src, sljit_sw srcw,
sljit_s32 type)
{
sljit_s32 dst_r, flags = GET_ALL_FLAGS(op);
sljit_uw cc, ins;
CHECK_ERROR();
- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
- ADJUST_LOCAL_OFFSET(src, srcw);
-
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
op = GET_OPCODE(op);
cc = get_cc(type & 0xff);
- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
if (op < SLJIT_ADD) {
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 0)));
FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc));
- return (dst_r == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2);
+ return SLJIT_SUCCESS;
}
ins = (op == SLJIT_AND ? AND_DP : (op == SLJIT_OR ? ORR_DP : EOR_DP));
- if ((op == SLJIT_OR || op == SLJIT_XOR) && FAST_IS_REG(dst) && dst == src) {
- FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc));
- /* The condition must always be set, even if the ORR/EOR is not executed above. */
- return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))) : SLJIT_SUCCESS;
- }
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- if (src & SLJIT_MEM) {
- FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
- src = TMP_REG1;
- srcw = 0;
- } else if (src & SLJIT_IMM) {
+ if (dst & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2));
+
+ FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, dst_r, SRC2_IMM | 1) & ~COND_MASK) | cc));
+
+ if (op == SLJIT_AND)
+ FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, dst_r, SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));
+
+ if (dst & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2));
+
+ if (flags & SLJIT_SET_Z)
+ return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG2, SLJIT_UNUSED, RM(dst_r)));
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_uw cc, tmp;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+ dst_reg &= ~SLJIT_I32_OP;
+
+ cc = get_cc(type & 0xff);
+
+ if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
+ tmp = get_imm(srcw);
+ if (tmp)
+ return push_inst(compiler, (EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_reg, SLJIT_UNUSED, tmp) & ~COND_MASK) | cc);
+
+ tmp = get_imm(~srcw);
+ if (tmp)
+ return push_inst(compiler, (EMIT_DATA_PROCESS_INS(MVN_DP, 0, dst_reg, SLJIT_UNUSED, tmp) & ~COND_MASK) | cc);
+
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+ tmp = (sljit_uw) srcw;
+ FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff)));
+ if (tmp <= 0xffff)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff));
+#else
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
src = TMP_REG1;
- srcw = 0;
+#endif
}
- FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 1) & ~COND_MASK) | cc));
- FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));
- if (dst_r == TMP_REG2)
- FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0));
-
- return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst_r))) : SLJIT_SUCCESS;
+ return push_inst(compiler, (EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_reg, SLJIT_UNUSED, RM(src)) & ~COND_MASK) | cc);
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
@@ -2536,7 +2294,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
sljit_s32 reg;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(1);
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
@@ -2554,16 +2311,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
set_const(const_, compiler);
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw, TMP_REG1));
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
- inline_set_jump_addr(addr, new_addr, 1);
+ inline_set_jump_addr(addr, executable_offset, new_target, 1);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- inline_set_const(addr, new_constant, 1);
+ inline_set_const(addr, executable_offset, new_constant, 1);
}
diff --git a/pcre/sljit/sljitNativeARM_64.c b/pcre/sljit/sljitNativeARM_64.c
index 75777a8e691..fd67f502536 100644
--- a/pcre/sljit/sljitNativeARM_64.c
+++ b/pcre/sljit/sljitNativeARM_64.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -76,6 +76,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {
#define BRK 0xd4200000
#define CBZ 0xb4000000
#define CLZ 0xdac01000
+#define CSEL 0x9a800000
#define CSINC 0x9a800400
#define EOR 0xca000000
#define EORI 0xd2000000
@@ -151,7 +152,7 @@ static SLJIT_INLINE void modify_imm64_const(sljit_ins* inst, sljit_uw new_imm)
inst[3] = MOVK | dst | ((new_imm >> 48) << 5) | (3 << 21);
}
-static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
{
sljit_sw diff;
sljit_uw target_addr;
@@ -165,9 +166,10 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
target_addr = jump->u.target;
else {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- target_addr = (sljit_uw)(code + jump->u.label->size);
+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
}
- diff = (sljit_sw)target_addr - (sljit_sw)(code_ptr + 4);
+
+ diff = (sljit_sw)target_addr - (sljit_sw)(code_ptr + 4) - executable_offset;
if (jump->flags & IS_COND) {
diff += sizeof(sljit_ins);
@@ -211,6 +213,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_sw executable_offset;
sljit_uw addr;
sljit_s32 dst;
@@ -228,6 +231,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ executable_offset = SLJIT_EXEC_OFFSET(code);
+
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
@@ -242,13 +247,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!jump || jump->addr >= word_count);
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
if (label && label->size == word_count) {
- label->addr = (sljit_uw)code_ptr;
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = code_ptr - code;
label = label->next;
}
if (jump && jump->addr == word_count) {
jump->addr = (sljit_uw)(code_ptr - 4);
- code_ptr -= detect_jump_type(jump, code_ptr, code);
+ code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
jump = jump->next;
}
if (const_ && const_->addr == word_count) {
@@ -263,7 +268,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} while (buf);
if (label && label->size == word_count) {
- label->addr = (sljit_uw)code_ptr;
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = code_ptr - code;
label = label->next;
}
@@ -277,9 +282,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
while (jump) {
do {
addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
- buf_ptr = (sljit_ins*)jump->addr;
+ buf_ptr = (sljit_ins *)jump->addr;
+
if (jump->flags & PATCH_B) {
- addr = (sljit_sw)(addr - jump->addr) >> 2;
+ addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
SLJIT_ASSERT((sljit_sw)addr <= 0x1ffffff && (sljit_sw)addr >= -0x2000000);
buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (addr & 0x3ffffff);
if (jump->flags & IS_COND)
@@ -287,7 +293,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
break;
}
if (jump->flags & PATCH_COND) {
- addr = (sljit_sw)(addr - jump->addr) >> 2;
+ addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
SLJIT_ASSERT((sljit_sw)addr <= 0x3ffff && (sljit_sw)addr >= -0x40000);
buf_ptr[0] = (buf_ptr[0] & ~0xffffe0) | ((addr & 0x7ffff) << 5);
break;
@@ -308,12 +314,37 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
}
compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
- SLJIT_ENABLE_EXEC(code, code_ptr);
+
+ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
SLJIT_CACHE_FLUSH(code, code_ptr);
return code;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#else
+ /* Available by default. */
+ return 1;
+#endif
+
+ case SLJIT_HAS_PRE_UPDATE:
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_CMOV:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
/* --------------------------------------------------------------------- */
/* Core code generator functions. */
/* --------------------------------------------------------------------- */
@@ -366,7 +397,7 @@ static sljit_ins logical_imm(sljit_sw imm, sljit_s32 len)
uimm = (sljit_uw)imm;
while (1) {
if (len <= 0) {
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return 0;
}
mask = ((sljit_uw)1 << len) - 1;
@@ -636,7 +667,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
}
goto set_flags;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
@@ -703,7 +734,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
case SLJIT_NOT:
SLJIT_ASSERT(arg1 == TMP_REG1);
FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2)));
- goto set_flags;
+ break; /* Set flags. */
case SLJIT_NEG:
SLJIT_ASSERT(arg1 == TMP_REG1);
if (flags & SET_FLAGS)
@@ -711,8 +742,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
case SLJIT_CLZ:
SLJIT_ASSERT(arg1 == TMP_REG1);
- FAIL_IF(push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2)));
- goto set_flags;
+ return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2));
case SLJIT_ADD:
CHECK_FLAGS(1 << 29);
return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
@@ -741,24 +771,24 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
return push_inst(compiler, (AND ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
case SLJIT_OR:
FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
- goto set_flags;
+ break; /* Set flags. */
case SLJIT_XOR:
FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
- goto set_flags;
+ break; /* Set flags. */
case SLJIT_SHL:
FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
- goto set_flags;
+ break; /* Set flags. */
case SLJIT_LSHR:
FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
- goto set_flags;
+ break; /* Set flags. */
case SLJIT_ASHR:
FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
- goto set_flags;
+ break; /* Set flags. */
+ default:
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
}
- SLJIT_ASSERT_STOP();
- return SLJIT_SUCCESS;
-
set_flags:
if (flags & SET_FLAGS)
return push_inst(compiler, (SUBS ^ inv_bits) | RD(TMP_ZERO) | RN(dst) | RM(TMP_ZERO));
@@ -860,6 +890,10 @@ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flag
}
arg &= REG_MASK;
+
+ if (arg == SLJIT_UNUSED)
+ return 0;
+
if (argw >= 0 && (argw >> shift) <= 0xfff && (argw & ((1 << shift) - 1)) == 0) {
if (SLJIT_UNLIKELY(flags & ARG_TEST))
return 1;
@@ -920,21 +954,23 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
next_argw = 0;
}
- tmp_r = (flags & STORE) ? TMP_REG3 : reg;
+ tmp_r = ((flags & STORE) || (flags == (WORD_SIZE | SIGNED))) ? TMP_REG3 : reg;
if (SLJIT_UNLIKELY((flags & UPDATE) && (arg & REG_MASK))) {
/* Update only applies if a base register exists. */
other_r = OFFS_REG(arg);
if (!other_r) {
other_r = arg & REG_MASK;
- if (other_r != reg && argw >= 0 && argw <= 0xffffff) {
+ SLJIT_ASSERT(other_r != reg);
+
+ if (argw >= 0 && argw <= 0xffffff) {
if ((argw & 0xfff) != 0)
FAIL_IF(push_inst(compiler, ADDI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10)));
if (argw >> 12)
FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(other_r) | RN(other_r) | ((argw >> 12) << 10)));
return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(other_r));
}
- else if (other_r != reg && argw < 0 && argw >= -0xffffff) {
+ else if (argw < 0 && argw >= -0xffffff) {
argw = -argw;
if ((argw & 0xfff) != 0)
FAIL_IF(push_inst(compiler, SUBI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10)));
@@ -967,18 +1003,8 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
/* No caching here. */
arg &= REG_MASK;
- argw &= 0x3;
- if (!argw || argw == shift) {
- FAIL_IF(push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(other_r) | (argw ? (1 << 12) : 0)));
- return push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10));
- }
- if (arg != reg) {
- FAIL_IF(push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10)));
- return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg));
- }
- FAIL_IF(push_inst(compiler, ADD | RD(TMP_LR) | RN(arg) | RM(other_r) | (argw << 10)));
- FAIL_IF(push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(TMP_LR)));
- return push_inst(compiler, ORR | RD(arg) | RN(TMP_ZERO) | RM(TMP_LR));
+ FAIL_IF(push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(other_r)));
+ return push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r));
}
if (arg & OFFS_REG_MASK) {
@@ -999,16 +1025,16 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
}
}
- if (argw >= 0 && argw <= 0xffffff && (argw & ((1 << shift) - 1)) == 0) {
- FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_r) | RN(arg & REG_MASK) | ((argw >> 12) << 10)));
- return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30)
- | RT(reg) | RN(tmp_r) | ((argw & 0xfff) << (10 - shift)));
- }
-
diff = argw - next_argw;
next_arg = (arg & REG_MASK) && (arg == next_arg) && diff <= 0xfff && diff >= -0xfff && diff != 0;
arg &= REG_MASK;
+ if (arg != SLJIT_UNUSED && argw >= 0 && argw <= 0xffffff && (argw & ((1 << shift) - 1)) == 0) {
+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_r) | RN(arg) | ((argw >> 12) << 10)));
+ return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30)
+ | RT(reg) | RN(tmp_r) | ((argw & 0xfff) << (10 - shift)));
+ }
+
if (arg && compiler->cache_arg == SLJIT_MEM) {
if (compiler->cache_argw == argw)
return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3));
@@ -1291,6 +1317,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
compiler->cache_arg = 0;
compiler->cache_argw = 0;
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+ if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) {
+ SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4);
+
+ if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8)
+ dst = 5;
+ else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16)
+ dst = 3;
+ else
+ dst = 1;
+
+ /* Signed word sized load is the prefetch instruction. */
+ return emit_op_mem(compiler, WORD_SIZE | SIGNED, dst, src, srcw);
+ }
+ return SLJIT_SUCCESS;
+ }
+
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
op = GET_OPCODE(op);
@@ -1365,7 +1408,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
srcw = (sljit_s32)srcw;
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
flags = 0;
break;
}
@@ -1392,7 +1435,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
- flags = GET_FLAGS(op_flags) ? SET_FLAGS : 0;
+ flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;
mem_flags = WORD_SIZE;
if (op_flags & SLJIT_I32_OP) {
flags |= INT_OP;
@@ -1444,8 +1487,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
compiler->cache_arg = 0;
compiler->cache_argw = 0;
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+ return SLJIT_SUCCESS;
+
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
- flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
mem_flags = WORD_SIZE;
if (op & SLJIT_I32_OP) {
flags |= INT_OP;
@@ -1538,16 +1584,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
- return SLJIT_IS_FPU_AVAILABLE;
-#else
- /* Available by default. */
- return 1;
-#endif
-}
-
static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
{
sljit_u32 shift = MEM_SIZE_SHIFT(flags);
@@ -1605,7 +1641,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
- sljit_s32 dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
if (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64)
@@ -1618,7 +1654,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
FAIL_IF(push_inst(compiler, (FCVTZS ^ inv_bits) | RD(dst_r) | VN(src)));
- if (dst_r == TMP_REG1 && dst != SLJIT_UNUSED)
+ if (dst & SLJIT_MEM)
return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw);
return SLJIT_SUCCESS;
}
@@ -1776,10 +1812,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
- /* For UNUSED dst. Uncommon, but possible. */
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
if (FAST_IS_REG(dst))
return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR));
@@ -1857,7 +1889,7 @@ static sljit_uw get_cc(sljit_s32 type)
return 0x6;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return 0xe;
}
}
@@ -1883,7 +1915,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
struct sljit_jump *jump;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
CHECK_PTR(check_sljit_emit_jump(compiler, type));
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -1968,19 +1999,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src, sljit_sw srcw,
sljit_s32 type)
{
- sljit_s32 dst_r, flags, mem_flags;
+ sljit_s32 dst_r, src_r, flags, mem_flags;
sljit_ins cc;
CHECK_ERROR();
- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
- ADJUST_LOCAL_OFFSET(src, srcw);
-
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
cc = get_cc(type & 0xff);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
@@ -1994,26 +2020,50 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
mem_flags = WORD_SIZE;
if (op & SLJIT_I32_OP) {
flags |= INT_OP;
mem_flags = INT_SIZE;
}
- if (src & SLJIT_MEM) {
- FAIL_IF(emit_op_mem2(compiler, mem_flags, TMP_REG1, src, srcw, dst, dstw));
- src = TMP_REG1;
- srcw = 0;
- } else if (src & SLJIT_IMM)
- flags |= ARG1_IMM;
+ src_r = dst;
+
+ if (dst & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, mem_flags, TMP_REG1, dst, dstw, dst, dstw));
+ src_r = TMP_REG1;
+ }
FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(TMP_ZERO)));
- emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src, TMP_REG2);
+ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src_r, TMP_REG2);
- if (dst_r != TMP_REG1)
- return SLJIT_SUCCESS;
- return emit_op_mem2(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0);
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins inv_bits = (dst_reg & SLJIT_I32_OP) ? (1 << 31) : 0;
+ sljit_ins cc;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+ if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
+ if (dst_reg & SLJIT_I32_OP)
+ srcw = (sljit_s32)srcw;
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ cc = get_cc(type & 0xff);
+ dst_reg &= ~SLJIT_I32_OP;
+
+ return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(dst_reg) | RM(src));
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
@@ -2022,7 +2072,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
sljit_s32 dst_r;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(1);
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
@@ -2030,7 +2079,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, init_value));
if (dst & SLJIT_MEM)
@@ -2038,16 +2087,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_ins* inst = (sljit_ins*)addr;
- modify_imm64_const(inst, new_addr);
+ modify_imm64_const(inst, new_target);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 4);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
sljit_ins* inst = (sljit_ins*)addr;
modify_imm64_const(inst, new_constant);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 4);
}
diff --git a/pcre/sljit/sljitNativeARM_T2_32.c b/pcre/sljit/sljitNativeARM_T2_32.c
index 2952a3eeea4..29e5566a820 100644
--- a/pcre/sljit/sljitNativeARM_T2_32.c
+++ b/pcre/sljit/sljitNativeARM_T2_32.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -35,15 +35,14 @@ typedef sljit_u32 sljit_ins;
/* Last register + 1. */
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
-#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
-#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 5)
+#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4)
#define TMP_FREG1 (0)
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
-static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
- 0, 0, 1, 2, 12, 11, 10, 9, 8, 7, 6, 5, 13, 3, 4, 14, 15
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
+ 0, 0, 1, 2, 12, 11, 10, 9, 8, 7, 6, 5, 4, 13, 3, 14, 15
};
#define COPY_BITS(src, from, to, bits) \
@@ -108,7 +107,11 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
#define BLX 0x4780
#define BX 0x4700
#define CLZ 0xfab0f080
+#define CMNI_W 0xf1100f00
+#define CMP 0x4280
#define CMPI 0x2800
+#define CMPI_W 0xf1b00f00
+#define CMP_X 0x4500
#define CMP_W 0xebb00f00
#define EORI 0xf0800000
#define EORS 0x4040
@@ -221,7 +224,7 @@ static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm)
inst[3] = dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16);
}
-static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code)
+static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)
{
sljit_sw diff;
@@ -232,7 +235,7 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_u1
/* Branch to ARM code is not optimized yet. */
if (!(jump->u.target & 0x1))
return 0;
- diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2)) >> 1;
+ diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset) >> 1;
}
else {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
@@ -276,7 +279,7 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_u1
return 0;
}
-static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
+static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump, sljit_sw executable_offset)
{
sljit_s32 type = (jump->flags >> 4) & 0xf;
sljit_sw diff;
@@ -290,10 +293,12 @@ static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
if (jump->flags & JUMP_ADDR) {
SLJIT_ASSERT(jump->u.target & 0x1);
- diff = ((sljit_sw)jump->u.target - (sljit_sw)(jump->addr + 4)) >> 1;
+ diff = ((sljit_sw)jump->u.target - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1;
+ }
+ else {
+ SLJIT_ASSERT(jump->u.label->addr & 0x1);
+ diff = ((sljit_sw)(jump->u.label->addr) - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1;
}
- else
- diff = ((sljit_sw)(jump->u.label->addr) - (sljit_sw)(jump->addr + 4)) >> 1;
jump_inst = (sljit_u16*)jump->addr;
switch (type) {
@@ -336,7 +341,7 @@ static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
else if (type == 6) /* Encoding T1 of 'BL' instruction */
jump_inst[1] |= 0xd000;
else
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
@@ -347,6 +352,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_u16 *buf_ptr;
sljit_u16 *buf_end;
sljit_uw half_count;
+ sljit_sw executable_offset;
struct sljit_label *label;
struct sljit_jump *jump;
@@ -362,6 +368,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
half_count = 0;
+ executable_offset = SLJIT_EXEC_OFFSET(code);
+
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
@@ -376,13 +384,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!jump || jump->addr >= half_count);
SLJIT_ASSERT(!const_ || const_->addr >= half_count);
if (label && label->size == half_count) {
- label->addr = ((sljit_uw)code_ptr) | 0x1;
+ label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
label->size = code_ptr - code;
label = label->next;
}
if (jump && jump->addr == half_count) {
jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8);
- code_ptr -= detect_jump_type(jump, code_ptr, code);
+ code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
jump = jump->next;
}
if (const_ && const_->addr == half_count) {
@@ -397,7 +405,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} while (buf);
if (label && label->size == half_count) {
- label->addr = ((sljit_uw)code_ptr) | 0x1;
+ label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
label->size = code_ptr - code;
label = label->next;
}
@@ -409,18 +417,43 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = compiler->jumps;
while (jump) {
- set_jump_instruction(jump);
+ set_jump_instruction(jump, executable_offset);
jump = jump->next;
}
compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_u16);
- SLJIT_ENABLE_EXEC(code, code_ptr);
+
+ code = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
SLJIT_CACHE_FLUSH(code, code_ptr);
/* Set thumb mode flag. */
return (void*)((sljit_uw)code | 0x1);
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#else
+ /* Available by default. */
+ return 1;
+#endif
+
+ case SLJIT_HAS_PRE_UPDATE:
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_CMOV:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
/* --------------------------------------------------------------------- */
/* Core code generator functions. */
/* --------------------------------------------------------------------- */
@@ -501,24 +534,20 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst,
#define ARG1_IMM 0x0010000
#define ARG2_IMM 0x0020000
-#define KEEP_FLAGS 0x0040000
/* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */
#define SET_FLAGS 0x0100000
#define UNUSED_RETURN 0x0200000
-#define SLOW_DEST 0x0400000
-#define SLOW_SRC1 0x0800000
-#define SLOW_SRC2 0x1000000
static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 dst, sljit_uw arg1, sljit_uw arg2)
{
/* dst must be register, TMP_REG1
- arg1 must be register, TMP_REG1, imm
- arg2 must be register, TMP_REG2, imm */
+ arg1 must be register, imm
+ arg2 must be register, imm */
sljit_s32 reg;
sljit_uw imm, nimm;
if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {
- /* Both are immediates. */
+ /* Both are immediates, no temporaries are used. */
flags &= ~ARG1_IMM;
FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));
arg1 = TMP_REG1;
@@ -534,7 +563,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
/* No form with immediate operand. */
break;
case SLJIT_MOV:
- SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1);
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG2);
return load_immediate(compiler, dst, imm);
case SLJIT_NOT:
if (!(flags & SET_FLAGS))
@@ -544,7 +573,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
break;
case SLJIT_ADD:
nimm = -imm;
- if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
+ if (IS_2_LO_REGS(reg, dst)) {
if (imm <= 0x7)
return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
if (nimm <= 0x7)
@@ -562,9 +591,12 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
if (nimm <= 0xfff)
return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm));
}
- imm = get_imm(imm);
- if (imm != INVALID_IMM)
- return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ nimm = get_imm(imm);
+ if (nimm != INVALID_IMM)
+ return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
+ nimm = get_imm(-imm);
+ if (nimm != INVALID_IMM)
+ return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
break;
case SLJIT_ADDC:
imm = get_imm(imm);
@@ -572,16 +604,27 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
break;
case SLJIT_SUB:
+ /* SUB operation can be replaced by ADD because of the negative carry flag. */
if (flags & ARG1_IMM) {
- if (!(flags & KEEP_FLAGS) && imm == 0 && IS_2_LO_REGS(reg, dst))
+ if (imm == 0 && IS_2_LO_REGS(reg, dst))
return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg));
imm = get_imm(imm);
if (imm != INVALID_IMM)
return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
break;
}
+ if (flags & UNUSED_RETURN) {
+ if (imm <= 0xff && reg_map[reg] <= 7)
+ return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
+ nimm = get_imm(imm);
+ if (nimm != INVALID_IMM)
+ return push_inst32(compiler, CMPI_W | RN4(reg) | nimm);
+ nimm = get_imm(-imm);
+ if (nimm != INVALID_IMM)
+ return push_inst32(compiler, CMNI_W | RN4(reg) | nimm);
+ }
nimm = -imm;
- if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
+ if (IS_2_LO_REGS(reg, dst)) {
if (imm <= 0x7)
return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
if (nimm <= 0x7)
@@ -592,8 +635,6 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
if (nimm <= 0xff)
return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst));
}
- if (imm <= 0xff && (flags & UNUSED_RETURN))
- return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
}
if (!(flags & SET_FLAGS)) {
if (imm <= 0xfff)
@@ -601,9 +642,12 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
if (nimm <= 0xfff)
return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm));
}
- imm = get_imm(imm);
- if (imm != INVALID_IMM)
- return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ nimm = get_imm(imm);
+ if (nimm != INVALID_IMM)
+ return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
+ nimm = get_imm(-imm);
+ if (nimm != INVALID_IMM)
+ return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
break;
case SLJIT_SUBC:
if (flags & ARG1_IMM)
@@ -648,31 +692,35 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
}
switch (flags & 0xffff) {
case SLJIT_SHL:
- if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
+ if (IS_2_LO_REGS(dst, reg))
return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6));
return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
case SLJIT_LSHR:
- if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
+ if (IS_2_LO_REGS(dst, reg))
return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6));
return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
default: /* SLJIT_ASHR */
- if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
+ if (IS_2_LO_REGS(dst, reg))
return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6));
return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
}
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
if (flags & ARG2_IMM) {
- FAIL_IF(load_immediate(compiler, TMP_REG2, arg2));
- arg2 = TMP_REG2;
+ imm = arg2;
+ arg2 = (arg1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(load_immediate(compiler, arg2, imm));
}
else {
- FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));
- arg1 = TMP_REG1;
+ imm = arg1;
+ arg1 = (arg2 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(load_immediate(compiler, arg1, imm));
}
+
+ SLJIT_ASSERT(arg1 != arg2);
}
/* Both arguments are registers. */
@@ -685,104 +733,102 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
case SLJIT_MOVU_U32:
case SLJIT_MOVU_S32:
case SLJIT_MOVU_P:
- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
if (dst == arg2)
return SLJIT_SUCCESS;
return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));
case SLJIT_MOV_U8:
case SLJIT_MOVU_U8:
- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
if (IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, UXTB | RD3(dst) | RN3(arg2));
return push_inst32(compiler, UXTB_W | RD4(dst) | RM4(arg2));
case SLJIT_MOV_S8:
case SLJIT_MOVU_S8:
- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
if (IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, SXTB | RD3(dst) | RN3(arg2));
return push_inst32(compiler, SXTB_W | RD4(dst) | RM4(arg2));
case SLJIT_MOV_U16:
case SLJIT_MOVU_U16:
- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
if (IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, UXTH | RD3(dst) | RN3(arg2));
return push_inst32(compiler, UXTH_W | RD4(dst) | RM4(arg2));
case SLJIT_MOV_S16:
case SLJIT_MOVU_S16:
- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
if (IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, SXTH | RD3(dst) | RN3(arg2));
return push_inst32(compiler, SXTH_W | RD4(dst) | RM4(arg2));
case SLJIT_NOT:
- SLJIT_ASSERT(arg1 == TMP_REG1);
- if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+ SLJIT_ASSERT(arg1 == TMP_REG2);
+ if (IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, MVNS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(arg2));
case SLJIT_CLZ:
- SLJIT_ASSERT(arg1 == TMP_REG1);
+ SLJIT_ASSERT(arg1 == TMP_REG2);
FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2)));
- if (flags & SET_FLAGS) {
- if (reg_map[dst] <= 7)
- return push_inst16(compiler, CMPI | RDN3(dst));
- return push_inst32(compiler, ADD_WI | SET_FLAGS | RN4(dst) | RD4(dst));
- }
return SLJIT_SUCCESS;
case SLJIT_ADD:
- if (!(flags & KEEP_FLAGS) && IS_3_LO_REGS(dst, arg1, arg2))
+ if (IS_3_LO_REGS(dst, arg1, arg2))
return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2));
if (dst == arg1 && !(flags & SET_FLAGS))
return push_inst16(compiler, ADD | SET_REGS44(dst, arg2));
return push_inst32(compiler, ADD_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_ADDC:
- if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_SUB:
- if (!(flags & KEEP_FLAGS) && IS_3_LO_REGS(dst, arg1, arg2))
+ if (flags & UNUSED_RETURN) {
+ if (IS_2_LO_REGS(arg1, arg2))
+ return push_inst16(compiler, CMP | RD3(arg1) | RN3(arg2));
+ return push_inst16(compiler, CMP_X | SET_REGS44(arg1, arg2));
+ }
+ if (IS_3_LO_REGS(dst, arg1, arg2))
return push_inst16(compiler, SUBS | RD3(dst) | RN3(arg1) | RM3(arg2));
return push_inst32(compiler, SUB_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_SUBC:
- if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, SBCS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, SBC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_MUL:
if (!(flags & SET_FLAGS))
return push_inst32(compiler, MUL | RD4(dst) | RN4(arg1) | RM4(arg2));
- SLJIT_ASSERT(reg_map[TMP_REG2] <= 7 && dst != TMP_REG2);
+ SLJIT_ASSERT(dst != TMP_REG2);
FAIL_IF(push_inst32(compiler, SMULL | RT4(dst) | RD4(TMP_REG2) | RN4(arg1) | RM4(arg2)));
/* cmp TMP_REG2, dst asr #31. */
return push_inst32(compiler, CMP_W | RN4(TMP_REG2) | 0x70e0 | RM4(dst));
case SLJIT_AND:
- if (!(flags & KEEP_FLAGS)) {
- if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
- return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2));
- if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2))
- return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2));
- }
+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2));
+ if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2))
+ return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2));
return push_inst32(compiler, AND_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_OR:
- if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, ORRS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, ORR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_XOR:
- if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_SHL:
- if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_LSHR:
- if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_ASHR:
- if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
}
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
}
@@ -792,9 +838,9 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
#define WORD_SIZE 0x00
#define BYTE_SIZE 0x04
#define HALF_SIZE 0x08
+#define PRELOAD 0x0c
#define UPDATE 0x10
-#define ARG_TEST 0x20
#define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE)))
#define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift)))
@@ -850,7 +896,7 @@ static const sljit_ins sljit_mem16_imm5[12] = {
#define MEM_IMM8 0xc00
#define MEM_IMM12 0x800000
-static const sljit_ins sljit_mem32[12] = {
+static const sljit_ins sljit_mem32[13] = {
/* w u l */ 0xf8500000 /* ldr.w */,
/* w u s */ 0xf8400000 /* str.w */,
/* w s l */ 0xf8500000 /* ldr.w */,
@@ -865,6 +911,8 @@ static const sljit_ins sljit_mem32[12] = {
/* h u s */ 0xf8200000 /* strsh.w */,
/* h s l */ 0xf9300000 /* ldrsh.w */,
/* h s s */ 0xf8200000 /* strsh.w */,
+
+/* p u l */ 0xf8100000 /* pld */,
};
/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
@@ -888,20 +936,67 @@ static sljit_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst,
return SLJIT_ERR_UNSUPPORTED;
}
-/* Can perform an operation using at most 1 instruction. */
-static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
+static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
{
- sljit_s32 other_r, shift;
+ sljit_s32 other_r;
+ sljit_s32 update = flags & UPDATE;
+ sljit_uw tmp;
SLJIT_ASSERT(arg & SLJIT_MEM);
+ SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
+ flags &= ~UPDATE;
+ arg &= ~SLJIT_MEM;
- if (SLJIT_UNLIKELY(flags & UPDATE)) {
- if ((arg & REG_MASK) && !(arg & OFFS_REG_MASK) && argw <= 0xff && argw >= -0xff) {
- if (SLJIT_UNLIKELY(flags & ARG_TEST))
- return 1;
+ if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
+ tmp = get_imm(argw & ~0xfff);
+ if (tmp != INVALID_IMM) {
+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(tmp_reg) | tmp));
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg) | (argw & 0xfff));
+ }
- flags &= ~UPDATE;
+ FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+ if (IS_2_LO_REGS(reg, tmp_reg) && sljit_mem16_imm5[flags])
+ return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(tmp_reg));
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg));
+ }
+
+ if (SLJIT_UNLIKELY(update)) {
+ SLJIT_ASSERT(reg != arg);
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ other_r = OFFS_REG(arg);
arg &= 0xf;
+
+ if (IS_3_LO_REGS(reg, arg, other_r))
+ FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
+ else
+ FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r)));
+ return push_inst16(compiler, ADD | SET_REGS44(arg, other_r));
+ }
+
+ if (argw > 0xff) {
+ tmp = get_imm(argw & ~0xff);
+ if (tmp != INVALID_IMM) {
+ push_inst32(compiler, ADD_WI | RD4(arg) | RN4(arg) | tmp);
+ argw = argw & 0xff;
+ }
+ }
+ else if (argw < -0xff) {
+ tmp = get_imm(-argw & ~0xff);
+ if (tmp != INVALID_IMM) {
+ push_inst32(compiler, SUB_WI | RD4(arg) | RN4(arg) | tmp);
+ argw = -(-argw & 0xff);
+ }
+ }
+
+ if (argw == 0) {
+ if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags])
+ return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg));
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg));
+ }
+
+ if (argw <= 0xff && argw >= -0xff) {
if (argw >= 0)
argw |= 0x200;
else {
@@ -909,219 +1004,83 @@ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flag
}
SLJIT_ASSERT(argw >= 0 && (argw & 0xff) <= 0xff);
- FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | 0x100 | argw));
- return -1;
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | 0x100 | argw);
}
- return 0;
+
+ FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+
+ SLJIT_ASSERT(reg != tmp_reg);
+
+ if (IS_3_LO_REGS(reg, arg, tmp_reg))
+ FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp_reg)));
+ else
+ FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg)));
+ return push_inst16(compiler, ADD | SET_REGS44(arg, tmp_reg));
}
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
- if (SLJIT_UNLIKELY(flags & ARG_TEST))
- return 1;
-
argw &= 0x3;
other_r = OFFS_REG(arg);
arg &= 0xf;
if (!argw && IS_3_LO_REGS(reg, arg, other_r))
- FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
- else
- FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4)));
- return -1;
+ return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r));
+ return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4));
}
- if (!(arg & REG_MASK) || argw > 0xfff || argw < -0xff)
- return 0;
+ if (argw > 0xfff) {
+ tmp = get_imm(argw & ~0xfff);
+ if (tmp != INVALID_IMM) {
+ push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | tmp);
+ arg = tmp_reg;
+ argw = argw & 0xfff;
+ }
+ }
+ else if (argw < -0xff) {
+ tmp = get_imm(-argw & ~0xff);
+ if (tmp != INVALID_IMM) {
+ push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp);
+ arg = tmp_reg;
+ argw = -(-argw & 0xff);
+ }
+ }
- if (SLJIT_UNLIKELY(flags & ARG_TEST))
- return 1;
-
- arg &= 0xf;
if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {
- shift = 3;
+ tmp = 3;
if (IS_WORD_SIZE(flags)) {
if (OFFSET_CHECK(0x1f, 2))
- shift = 2;
+ tmp = 2;
}
else if (flags & BYTE_SIZE)
{
if (OFFSET_CHECK(0x1f, 0))
- shift = 0;
+ tmp = 0;
}
else {
SLJIT_ASSERT(flags & HALF_SIZE);
if (OFFSET_CHECK(0x1f, 1))
- shift = 1;
+ tmp = 1;
}
- if (shift != 3) {
- FAIL_IF(push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - shift))));
- return -1;
- }
+ if (tmp < 3)
+ return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - tmp)));
+ }
+ else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && OFFSET_CHECK(0xff, 2) && reg_map[reg] <= 7) {
+ /* SP based immediate. */
+ return push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2));
}
- /* SP based immediate. */
- if (SLJIT_UNLIKELY(arg == SLJIT_SP) && OFFSET_CHECK(0xff, 2) && IS_WORD_SIZE(flags) && reg_map[reg] <= 7) {
- FAIL_IF(push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2)));
- return -1;
- }
+ if (argw >= 0 && argw <= 0xfff)
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw);
+ else if (argw < 0 && argw >= -0xff)
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | -argw);
- if (argw >= 0)
- FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw));
- else
- FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | -argw));
- return -1;
-}
+ SLJIT_ASSERT(arg != tmp_reg);
-/* see getput_arg below.
- Note: can_cache is called only for binary operators. Those
- operators always uses word arguments without write back. */
-static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
-{
- sljit_sw diff;
- if ((arg & OFFS_REG_MASK) || !(next_arg & SLJIT_MEM))
- return 0;
-
- if (!(arg & REG_MASK)) {
- diff = argw - next_argw;
- if (diff <= 0xfff && diff >= -0xfff)
- return 1;
- return 0;
- }
-
- if (argw == next_argw)
- return 1;
-
- diff = argw - next_argw;
- if (arg == next_arg && diff <= 0xfff && diff >= -0xfff)
- return 1;
-
- return 0;
-}
-
-/* Emit the necessary instructions. See can_cache above. */
-static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
- sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
-{
- sljit_s32 tmp_r, other_r;
- sljit_sw diff;
-
- SLJIT_ASSERT(arg & SLJIT_MEM);
- if (!(next_arg & SLJIT_MEM)) {
- next_arg = 0;
- next_argw = 0;
- }
-
- tmp_r = (flags & STORE) ? TMP_REG3 : reg;
-
- if (SLJIT_UNLIKELY((flags & UPDATE) && (arg & REG_MASK))) {
- /* Update only applies if a base register exists. */
- /* There is no caching here. */
- other_r = OFFS_REG(arg);
- arg &= 0xf;
- flags &= ~UPDATE;
-
- if (!other_r) {
- if (!(argw & ~0xfff)) {
- FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw));
- return push_inst32(compiler, ADDWI | RD4(arg) | RN4(arg) | IMM12(argw));
- }
-
- if (compiler->cache_arg == SLJIT_MEM) {
- if (argw == compiler->cache_argw) {
- other_r = TMP_REG3;
- argw = 0;
- }
- else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
- FAIL_IF(compiler->error);
- compiler->cache_argw = argw;
- other_r = TMP_REG3;
- argw = 0;
- }
- }
-
- if (argw) {
- FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
- compiler->cache_arg = SLJIT_MEM;
- compiler->cache_argw = argw;
- other_r = TMP_REG3;
- argw = 0;
- }
- }
-
- argw &= 0x3;
- if (!argw && IS_3_LO_REGS(reg, arg, other_r)) {
- FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
- return push_inst16(compiler, ADD | SET_REGS44(arg, other_r));
- }
- FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4)));
- return push_inst32(compiler, ADD_W | RD4(arg) | RN4(arg) | RM4(other_r) | (argw << 6));
- }
- flags &= ~UPDATE;
-
- SLJIT_ASSERT(!(arg & OFFS_REG_MASK));
-
- if (compiler->cache_arg == arg) {
- diff = argw - compiler->cache_argw;
- if (!(diff & ~0xfff))
- return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | diff);
- if (!((compiler->cache_argw - argw) & ~0xff))
- return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(TMP_REG3) | (compiler->cache_argw - argw));
- if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, diff) != SLJIT_ERR_UNSUPPORTED) {
- FAIL_IF(compiler->error);
- return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0);
- }
- }
-
- next_arg = (arg & REG_MASK) && (arg == next_arg) && (argw != next_argw);
- arg &= 0xf;
- if (arg && compiler->cache_arg == SLJIT_MEM) {
- if (compiler->cache_argw == argw)
- return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
- if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
- FAIL_IF(compiler->error);
- compiler->cache_argw = argw;
- return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
- }
- }
-
- compiler->cache_argw = argw;
- if (next_arg && emit_set_delta(compiler, TMP_REG3, arg, argw) != SLJIT_ERR_UNSUPPORTED) {
- FAIL_IF(compiler->error);
- compiler->cache_arg = SLJIT_MEM | arg;
- arg = 0;
- }
- else {
- FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
- compiler->cache_arg = SLJIT_MEM;
-
- diff = argw - next_argw;
- if (next_arg && diff <= 0xfff && diff >= -0xfff) {
- FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, arg)));
- compiler->cache_arg = SLJIT_MEM | arg;
- arg = 0;
- }
- }
-
- if (arg)
- return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
- return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0);
-}
-
-static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
-{
- if (getput_arg_fast(compiler, flags, reg, arg, argw))
- return compiler->error;
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
-}
-
-static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
-{
- if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
- return compiler->error;
- return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+ FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+ if (IS_3_LO_REGS(reg, arg, tmp_reg))
+ return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp_reg));
+ return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg));
}
/* --------------------------------------------------------------------- */
@@ -1133,14 +1092,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
sljit_s32 size, i, tmp;
- sljit_ins push;
+ sljit_ins push = 0;
CHECK_ERROR();
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
- push = (1 << 4);
-
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
for (i = SLJIT_S0; i >= tmp; i--)
push |= 1 << reg_map[i];
@@ -1153,7 +1110,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
: push_inst16(compiler, PUSH | (1 << 8) | push));
/* Stack must be aligned to 8 bytes: (LR, R4) */
- size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
local_size = ((size + local_size + 7) & ~7) - size;
compiler->local_size = local_size;
if (local_size > 0) {
@@ -1183,7 +1140,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
- size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
compiler->local_size = ((size + local_size + 7) & ~7) - size;
return SLJIT_SUCCESS;
}
@@ -1191,7 +1148,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
{
sljit_s32 i, tmp;
- sljit_ins pop;
+ sljit_ins pop = 0;
CHECK_ERROR();
CHECK(check_sljit_emit_return(compiler, op, src, srcw));
@@ -1205,8 +1162,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_SP, SLJIT_SP, compiler->local_size));
}
- pop = (1 << 4);
-
tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
for (i = SLJIT_S0; i >= tmp; i--)
pop |= 1 << reg_map[i];
@@ -1264,7 +1219,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
case SLJIT_DIV_UW:
case SLJIT_DIV_SW:
SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
- SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12, bad_register_mapping);
+ SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12);
saved_reg_count = 0;
if (compiler->scratches >= 4)
@@ -1324,8 +1279,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+ /* Since TMP_PC has index 15, IS_2_LO_REGS and IS_3_LO_REGS checks always fail. */
+ if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
+ return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1);
+ return SLJIT_SUCCESS;
+ }
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
@@ -1385,31 +1344,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
srcw = (sljit_s16)srcw;
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
flags = 0;
break;
}
if (src & SLJIT_IMM)
- FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw));
+ FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, srcw));
else if (src & SLJIT_MEM) {
- if (getput_arg_fast(compiler, flags, dst_r, src, srcw))
- FAIL_IF(compiler->error);
- else
- FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw));
+ FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, ((flags & UPDATE) && dst_r == TMP_REG1) ? TMP_REG2 : TMP_REG1));
} else {
if (dst_r != TMP_REG1)
- return emit_op_imm(compiler, op, dst_r, TMP_REG1, src);
+ return emit_op_imm(compiler, op, dst_r, TMP_REG2, src);
dst_r = src;
}
- if (dst & SLJIT_MEM) {
- if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw))
- return compiler->error;
- else
- return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0);
- }
- return SLJIT_SUCCESS;
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+
+ return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, (dst_r == TMP_REG1) ? TMP_REG2 : TMP_REG1);
}
if (op == SLJIT_NEG) {
@@ -1420,29 +1373,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
return sljit_emit_op2(compiler, SLJIT_SUB | op_flags, dst, dstw, SLJIT_IMM, 0, src, srcw);
}
- flags = (GET_FLAGS(op_flags) ? SET_FLAGS : 0) | ((op_flags & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0);
- if (src & SLJIT_MEM) {
- if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src, srcw))
- FAIL_IF(compiler->error);
- else
- FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src, srcw, dst, dstw));
- src = TMP_REG2;
- }
+ flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;
if (src & SLJIT_IMM)
flags |= ARG2_IMM;
+ else if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
+ srcw = TMP_REG1;
+ }
else
srcw = src;
- emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, srcw);
+ emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, srcw);
- if (dst & SLJIT_MEM) {
- if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw))
- return compiler->error;
- else
- return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0);
- }
- return SLJIT_SUCCESS;
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
@@ -1450,7 +1396,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- sljit_s32 dst_r, flags;
+ sljit_s32 dst_reg, flags, src2_reg;
CHECK_ERROR();
CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1458,70 +1404,39 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+ return SLJIT_SUCCESS;
- dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
- flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0);
-
- if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, WORD_SIZE | STORE | ARG_TEST, TMP_REG1, dst, dstw))
- flags |= SLOW_DEST;
-
- if (src1 & SLJIT_MEM) {
- if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG1, src1, src1w))
- FAIL_IF(compiler->error);
- else
- flags |= SLOW_SRC1;
- }
- if (src2 & SLJIT_MEM) {
- if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src2, src2w))
- FAIL_IF(compiler->error);
- else
- flags |= SLOW_SRC2;
- }
-
- if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
- if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
- FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, src1, src1w));
- FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, dst, dstw));
- }
- else {
- FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, src2, src2w));
- FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, dst, dstw));
- }
- }
- else if (flags & SLOW_SRC1)
- FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, dst, dstw));
- else if (flags & SLOW_SRC2)
- FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, dst, dstw));
-
- if (src1 & SLJIT_MEM)
- src1 = TMP_REG1;
- if (src2 & SLJIT_MEM)
- src2 = TMP_REG2;
+ dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
if (src1 & SLJIT_IMM)
flags |= ARG1_IMM;
+ else if (src1 & SLJIT_MEM) {
+ emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1);
+ src1w = TMP_REG1;
+ }
else
src1w = src1;
+
if (src2 & SLJIT_IMM)
flags |= ARG2_IMM;
+ else if (src2 & SLJIT_MEM) {
+ src2_reg = (!(flags & ARG1_IMM) && (src1w == TMP_REG1)) ? TMP_REG2 : TMP_REG1;
+ emit_op_mem(compiler, WORD_SIZE, src2_reg, src2, src2w, src2_reg);
+ src2w = src2_reg;
+ }
else
src2w = src2;
if (dst == SLJIT_UNUSED)
flags |= UNUSED_RETURN;
- emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w);
+ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_reg, src1w, src2w);
- if (dst & SLJIT_MEM) {
- if (!(flags & SLOW_DEST)) {
- getput_arg_fast(compiler, WORD_SIZE | STORE, dst_r, dst, dstw);
- return compiler->error;
- }
- return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, 0, 0);
- }
- return SLJIT_SUCCESS;
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG2);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
@@ -1551,21 +1466,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
- return SLJIT_IS_FPU_AVAILABLE;
-#else
- /* Available by default. */
- return 1;
-#endif
-}
-
#define FPU_LOAD (1 << 20)
static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
{
- sljit_sw tmp;
sljit_uw imm;
sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD));
@@ -1573,8 +1477,8 @@ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags,
/* Fast loads and stores. */
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
- FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG2) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((argw & 0x3) << 6)));
- arg = SLJIT_MEM | TMP_REG2;
+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((argw & 0x3) << 6)));
+ arg = SLJIT_MEM | TMP_REG1;
argw = 0;
}
@@ -1585,21 +1489,6 @@ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags,
return push_inst32(compiler, inst | RN4(arg & REG_MASK) | DD4(reg) | (-argw >> 2));
}
- /* Slow cases */
- SLJIT_ASSERT(!(arg & OFFS_REG_MASK));
- if (compiler->cache_arg == arg) {
- tmp = argw - compiler->cache_argw;
- if (!(tmp & ~0x3fc))
- return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg) | (tmp >> 2));
- if (!(-tmp & ~0x3fc))
- return push_inst32(compiler, inst | RN4(TMP_REG3) | DD4(reg) | (-tmp >> 2));
- if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, tmp) != SLJIT_ERR_UNSUPPORTED) {
- FAIL_IF(compiler->error);
- compiler->cache_argw = argw;
- return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg));
- }
- }
-
if (arg & REG_MASK) {
if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {
FAIL_IF(compiler->error);
@@ -1618,19 +1507,18 @@ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags,
}
}
- compiler->cache_arg = arg;
- compiler->cache_argw = argw;
-
- FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+ FAIL_IF(load_immediate(compiler, TMP_REG1, argw));
if (arg & REG_MASK)
- FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, (arg & REG_MASK))));
- return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg));
+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, (arg & REG_MASK))));
+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg));
}
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
+ op ^= SLJIT_F32_OP;
+
if (src & SLJIT_MEM) {
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw));
src = TMP_FREG1;
@@ -1638,9 +1526,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_F32_OP) | DD4(TMP_FREG1) | DM4(src)));
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
if (FAST_IS_REG(dst))
return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | DN4(TMP_FREG1));
@@ -1654,6 +1539,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
{
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+ op ^= SLJIT_F32_OP;
+
if (FAST_IS_REG(src))
FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | DN4(TMP_FREG1)));
else if (src & SLJIT_MEM) {
@@ -1676,6 +1563,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
+ op ^= SLJIT_F32_OP;
+
if (src1 & SLJIT_MEM) {
emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
src1 = TMP_FREG1;
@@ -1697,16 +1586,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
sljit_s32 dst_r;
CHECK_ERROR();
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
- op ^= SLJIT_F32_OP;
SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error);
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+ if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
+ op ^= SLJIT_F32_OP;
+
if (src & SLJIT_MEM) {
emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw);
src = dst_r;
@@ -1751,8 +1639,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
op ^= SLJIT_F32_OP;
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
@@ -1797,21 +1683,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
- /* For UNUSED dst. Uncommon, but possible. */
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
if (FAST_IS_REG(dst))
- return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3));
+ return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2));
/* Memory. */
- if (getput_arg_fast(compiler, WORD_SIZE | STORE, TMP_REG3, dst, dstw))
- return compiler->error;
- /* TMP_REG3 is used for caching. */
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, TMP_REG3)));
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0);
+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
@@ -1820,21 +1698,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
+
if (FAST_IS_REG(src))
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src)));
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));
else if (src & SLJIT_MEM) {
- if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw))
- FAIL_IF(compiler->error);
- else {
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src, srcw, 0, 0));
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, TMP_REG2)));
- }
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));
}
else if (src & SLJIT_IMM)
- FAIL_IF(load_immediate(compiler, TMP_REG3, srcw));
- return push_inst16(compiler, BLX | RN3(TMP_REG3));
+ FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
+ return push_inst16(compiler, BX | RN3(TMP_REG2));
}
/* --------------------------------------------------------------------- */
@@ -1891,7 +1764,7 @@ static sljit_uw get_cc(sljit_s32 type)
return 0x7;
default: /* SLJIT_JUMP */
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return 0xe;
}
}
@@ -1918,7 +1791,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
sljit_ins cc;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
CHECK_PTR(check_sljit_emit_jump(compiler, type));
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -1959,7 +1831,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
if (FAST_IS_REG(src))
return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src));
- FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw));
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw, TMP_REG1));
if (type >= SLJIT_FAST_CALL)
return push_inst16(compiler, BLX | RN3(TMP_REG1));
}
@@ -1976,23 +1848,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src, sljit_sw srcw,
sljit_s32 type)
{
sljit_s32 dst_r, flags = GET_ALL_FLAGS(op);
- sljit_ins cc, ins;
+ sljit_ins cc;
CHECK_ERROR();
- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
- ADJUST_LOCAL_OFFSET(src, srcw);
-
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
op = GET_OPCODE(op);
cc = get_cc(type & 0xff);
- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
if (op < SLJIT_ADD) {
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
@@ -2000,60 +1867,86 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 1));
FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 0));
} else {
+ /* The movsi (immediate) instruction does not set flags in IT block. */
FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1));
FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0));
}
- if (dst_r != TMP_REG2)
+ if (!(dst & SLJIT_MEM))
return SLJIT_SUCCESS;
- return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw);
+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2);
}
- ins = (op == SLJIT_AND ? ANDI : (op == SLJIT_OR ? ORRI : EORI));
- if ((op == SLJIT_OR || op == SLJIT_XOR) && FAST_IS_REG(dst) && dst == src) {
- /* Does not change the other bits. */
- FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
- FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst) | 1));
- if (flags & SLJIT_SET_E) {
- /* The condition must always be set, even if the ORRI/EORI is not executed above. */
- if (reg_map[dst] <= 7)
- return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst));
- return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst));
- }
- return SLJIT_SUCCESS;
- }
+ if (dst & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- if (src & SLJIT_MEM) {
- FAIL_IF(emit_op_mem2(compiler, WORD_SIZE, TMP_REG2, src, srcw, dst, dstw));
- src = TMP_REG2;
- srcw = 0;
- } else if (src & SLJIT_IMM) {
- FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
- src = TMP_REG2;
- srcw = 0;
- }
-
- if (op == SLJIT_AND || src != dst_r) {
+ if (op == SLJIT_AND) {
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
- FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1));
- FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 0));
+ FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 1));
+ FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 0));
}
else {
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
- FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1));
+ FAIL_IF(push_inst32(compiler, ((op == SLJIT_OR) ? ORRI : EORI) | RN4(dst_r) | RD4(dst_r) | 1));
}
- if (dst_r == TMP_REG2)
- FAIL_IF(emit_op_mem2(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0));
+ if (dst & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2));
- if (flags & SLJIT_SET_E) {
- /* The condition must always be set, even if the ORR/EORI is not executed above. */
- if (reg_map[dst_r] <= 7)
- return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst_r));
- return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r));
+ if (!(flags & SLJIT_SET_Z))
+ return SLJIT_SUCCESS;
+
+ /* The condition must always be set, even if the ORR/EORI is not executed above. */
+ if (reg_map[dst_r] <= 7)
+ return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst_r));
+ return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_uw cc, tmp;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+ dst_reg &= ~SLJIT_I32_OP;
+
+ cc = get_cc(type & 0xff);
+
+ if (!(src & SLJIT_IMM)) {
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst16(compiler, MOV | SET_REGS44(dst_reg, src));
}
- return SLJIT_SUCCESS;
+
+ tmp = (sljit_uw) srcw;
+
+ if (tmp < 0x10000) {
+ /* set low 16 bits, set hi 16 bits to 0. */
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst32(compiler, MOVW | RD4(dst_reg) |
+ COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff));
+ }
+
+ tmp = get_imm(srcw);
+ if (tmp != INVALID_IMM) {
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp);
+ }
+
+ tmp = get_imm(~srcw);
+ if (tmp != INVALID_IMM) {
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp);
+ }
+
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4));
+
+ tmp = (sljit_uw) srcw;
+ FAIL_IF(push_inst32(compiler, MOVW | RD4(dst_reg) |
+ COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff)));
+ return push_inst32(compiler, MOVT | RD4(dst_reg) |
+ COPY_BITS(tmp, 12 + 16, 16, 4) | COPY_BITS(tmp, 11 + 16, 26, 1) | COPY_BITS(tmp, 8 + 16, 12, 3) | ((tmp & 0xff0000) >> 16));
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
@@ -2062,7 +1955,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
sljit_s32 dst_r;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(1);
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
@@ -2070,24 +1962,26 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value));
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw));
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_u16 *inst = (sljit_u16*)addr;
- modify_imm32_const(inst, new_addr);
+ modify_imm32_const(inst, new_target);
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 4);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
sljit_u16 *inst = (sljit_u16*)addr;
modify_imm32_const(inst, new_constant);
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 4);
}
diff --git a/pcre/sljit/sljitNativeMIPS_32.c b/pcre/sljit/sljitNativeMIPS_32.c
index 5096e4f55ea..62e16106b12 100644
--- a/pcre/sljit/sljitNativeMIPS_32.c
+++ b/pcre/sljit/sljitNativeMIPS_32.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -40,35 +40,37 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_a
#define EMIT_LOGICAL(op_imm, op_norm) \
if (flags & SRC2_IMM) { \
- if (op & SLJIT_SET_E) \
+ if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
- if (CHECK_FLAGS(SLJIT_SET_E)) \
+ if (!(flags & UNUSED_DEST)) \
FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
} \
else { \
- if (op & SLJIT_SET_E) \
+ if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
- if (CHECK_FLAGS(SLJIT_SET_E)) \
+ if (!(flags & UNUSED_DEST)) \
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
}
#define EMIT_SHIFT(op_imm, op_v) \
if (flags & SRC2_IMM) { \
- if (op & SLJIT_SET_E) \
+ if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
- if (CHECK_FLAGS(SLJIT_SET_E)) \
+ if (!(flags & UNUSED_DEST)) \
FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
} \
else { \
- if (op & SLJIT_SET_E) \
+ if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
- if (CHECK_FLAGS(SLJIT_SET_E)) \
+ if (!(flags & UNUSED_DEST)) \
FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \
}
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
{
+ sljit_s32 is_overflow, is_carry, is_handled;
+
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
case SLJIT_MOV_U32:
@@ -93,8 +95,9 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
}
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
}
- else if (dst != src2)
- SLJIT_ASSERT_STOP();
+ else {
+ SLJIT_ASSERT(dst == src2);
+ }
return SLJIT_SUCCESS;
case SLJIT_MOV_U16:
@@ -111,24 +114,25 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
}
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
}
- else if (dst != src2)
- SLJIT_ASSERT_STOP();
+ else {
+ SLJIT_ASSERT(dst == src2);
+ }
return SLJIT_SUCCESS;
case SLJIT_NOT:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
- if (op & SLJIT_SET_E)
+ if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
- if (CHECK_FLAGS(SLJIT_SET_E))
+ if (!(flags & UNUSED_DEST))
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
return SLJIT_SUCCESS;
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
- if (op & SLJIT_SET_E)
+ if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
- if (CHECK_FLAGS(SLJIT_SET_E))
+ if (!(flags & UNUSED_DEST))
FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
#else
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
@@ -145,130 +149,192 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
- if (op & SLJIT_SET_E)
- return push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
#endif
return SLJIT_SUCCESS;
case SLJIT_ADD:
+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
if (flags & SRC2_IMM) {
- if (op & SLJIT_SET_O) {
+ if (is_overflow) {
if (src2 >= 0)
- FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
else
- FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
}
- if (op & SLJIT_SET_E)
+ else if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
- if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
+
+ if (is_overflow || is_carry) {
if (src2 >= 0)
- FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+ FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
else {
- FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
- FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+ FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
}
}
/* dst may be the same as src1 or src2. */
- if (CHECK_FLAGS(SLJIT_SET_E))
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
}
else {
- if (op & SLJIT_SET_O)
- FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- if (op & SLJIT_SET_E)
+ if (is_overflow)
+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ else if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
- if (op & (SLJIT_SET_C | SLJIT_SET_O))
- FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
+
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
/* dst may be the same as src1 or src2. */
- if (CHECK_FLAGS(SLJIT_SET_E))
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
}
/* a + b >= a | b (otherwise, the carry should be set to 1). */
- if (op & (SLJIT_SET_C | SLJIT_SET_O))
- FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
- if (!(op & SLJIT_SET_O))
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+ if (!is_overflow)
return SLJIT_SUCCESS;
- FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
- FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- return push_inst(compiler, SLL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
+ FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
case SLJIT_ADDC:
+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
if (flags & SRC2_IMM) {
- if (op & SLJIT_SET_C) {
+ if (is_carry) {
if (src2 >= 0)
- FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
else {
- FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
- FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
+ FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
}
}
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
} else {
- if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
/* dst may be the same as src1 or src2. */
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
}
- if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
- FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
- if (!(op & SLJIT_SET_C))
+ FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+ if (!is_carry)
return SLJIT_SUCCESS;
- /* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
- FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+ /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
/* Set carry flag. */
- return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
+ return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
case SLJIT_SUB:
- if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
src2 = TMP_REG2;
flags &= ~SRC2_IMM;
}
+ is_handled = 0;
+
if (flags & SRC2_IMM) {
- if (op & SLJIT_SET_O) {
- if (src2 >= 0)
- FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- else
- FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+ is_handled = 1;
}
- if (op & SLJIT_SET_E)
+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
+ FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+ is_handled = 1;
+ }
+ }
+
+ if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
+ is_handled = 1;
+
+ if (flags & SRC2_IMM) {
+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
+ }
+ else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)
+ {
+ FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+ }
+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
+ FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
+ }
+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)
+ {
+ FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+ }
+ }
+
+ if (is_handled) {
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
+ if (!(flags & UNUSED_DEST))
+ return push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst));
+ }
+ else {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ if (!(flags & UNUSED_DEST))
+ return push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst));
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
+ if (flags & SRC2_IMM) {
+ if (is_overflow) {
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ else
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ }
+ else if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
- if (op & (SLJIT_SET_C | SLJIT_SET_O))
- FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
/* dst may be the same as src1 or src2. */
- if (CHECK_FLAGS(SLJIT_SET_E))
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
}
else {
- if (op & SLJIT_SET_O)
- FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- if (op & SLJIT_SET_E)
+ if (is_overflow)
+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ else if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
- if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
- FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
- if (op & SLJIT_SET_U)
- FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
- if (op & SLJIT_SET_S) {
- FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
- FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
- }
+
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
/* dst may be the same as src1 or src2. */
- if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
}
- if (!(op & SLJIT_SET_O))
+ if (!is_overflow)
return SLJIT_SUCCESS;
- FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
- FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- return push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
+ FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
case SLJIT_SUBC:
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
@@ -277,28 +343,31 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
flags &= ~SRC2_IMM;
}
+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
if (flags & SRC2_IMM) {
- if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
/* dst may be the same as src1 or src2. */
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
}
else {
- if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
/* dst may be the same as src1 or src2. */
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
}
- if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG));
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
- FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
- return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
+ FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+ return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;
case SLJIT_MUL:
SLJIT_ASSERT(!(flags & SRC2_IMM));
- if (!(op & SLJIT_SET_O)) {
+
+ if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
#else
@@ -307,10 +376,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
#endif
}
FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
- FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG));
+ FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
- FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG));
- return push_inst(compiler, SUBU | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
+ FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
+ return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
case SLJIT_AND:
EMIT_LOGICAL(ANDI, AND);
@@ -337,7 +406,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return SLJIT_SUCCESS;
}
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
}
@@ -347,20 +416,22 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
- sljit_ins *inst = (sljit_ins*)addr;
+ sljit_ins *inst = (sljit_ins *)addr;
- inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
- inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
+ inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
+ inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_ins *inst = (sljit_ins*)addr;
+ sljit_ins *inst = (sljit_ins *)addr;
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
diff --git a/pcre/sljit/sljitNativeMIPS_64.c b/pcre/sljit/sljitNativeMIPS_64.c
index c7ee8c9c2e6..dd114bb27af 100644
--- a/pcre/sljit/sljitNativeMIPS_64.c
+++ b/pcre/sljit/sljitNativeMIPS_64.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -123,15 +123,15 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_a
#define EMIT_LOGICAL(op_imm, op_norm) \
if (flags & SRC2_IMM) { \
- if (op & SLJIT_SET_E) \
+ if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
- if (CHECK_FLAGS(SLJIT_SET_E)) \
+ if (!(flags & UNUSED_DEST)) \
FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
} \
else { \
- if (op & SLJIT_SET_E) \
+ if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
- if (CHECK_FLAGS(SLJIT_SET_E)) \
+ if (!(flags & UNUSED_DEST)) \
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
}
@@ -144,16 +144,16 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_a
} \
else \
ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \
- if (op & SLJIT_SET_E) \
+ if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
- if (CHECK_FLAGS(SLJIT_SET_E)) \
+ if (!(flags & UNUSED_DEST)) \
FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
} \
else { \
ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \
- if (op & SLJIT_SET_E) \
+ if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
- if (CHECK_FLAGS(SLJIT_SET_E)) \
+ if (!(flags & UNUSED_DEST)) \
FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \
}
@@ -161,6 +161,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
{
sljit_ins ins;
+ sljit_s32 is_overflow, is_carry, is_handled;
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
@@ -180,8 +181,9 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
}
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
}
- else if (dst != src2)
- SLJIT_ASSERT_STOP();
+ else {
+ SLJIT_ASSERT(dst == src2);
+ }
return SLJIT_SUCCESS;
case SLJIT_MOV_U16:
@@ -194,8 +196,9 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
}
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
}
- else if (dst != src2)
- SLJIT_ASSERT_STOP();
+ else {
+ SLJIT_ASSERT(dst == src2);
+ }
return SLJIT_SUCCESS;
case SLJIT_MOV_U32:
@@ -209,18 +212,18 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
case SLJIT_NOT:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
- if (op & SLJIT_SET_E)
+ if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
- if (CHECK_FLAGS(SLJIT_SET_E))
+ if (!(flags & UNUSED_DEST))
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
return SLJIT_SUCCESS;
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
- if (op & SLJIT_SET_E)
+ if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
- if (CHECK_FLAGS(SLJIT_SET_E))
+ if (!(flags & UNUSED_DEST))
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
#else
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
@@ -237,130 +240,192 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
- if (op & SLJIT_SET_E)
- return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
#endif
return SLJIT_SUCCESS;
case SLJIT_ADD:
+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
if (flags & SRC2_IMM) {
- if (op & SLJIT_SET_O) {
+ if (is_overflow) {
if (src2 >= 0)
- FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
else
- FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
}
- if (op & SLJIT_SET_E)
+ else if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
- if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
+
+ if (is_overflow || is_carry) {
if (src2 >= 0)
- FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+ FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
else {
- FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
- FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+ FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
}
}
/* dst may be the same as src1 or src2. */
- if (CHECK_FLAGS(SLJIT_SET_E))
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
}
else {
- if (op & SLJIT_SET_O)
- FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- if (op & SLJIT_SET_E)
+ if (is_overflow)
+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ else if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
- if (op & (SLJIT_SET_C | SLJIT_SET_O))
- FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
+
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
/* dst may be the same as src1 or src2. */
- if (CHECK_FLAGS(SLJIT_SET_E))
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
}
/* a + b >= a | b (otherwise, the carry should be set to 1). */
- if (op & (SLJIT_SET_C | SLJIT_SET_O))
- FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
- if (!(op & SLJIT_SET_O))
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+ if (!is_overflow)
return SLJIT_SUCCESS;
- FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
- FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- return push_inst(compiler, SELECT_OP(DSRL32, SLL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
case SLJIT_ADDC:
+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
if (flags & SRC2_IMM) {
- if (op & SLJIT_SET_C) {
+ if (is_carry) {
if (src2 >= 0)
- FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
else {
- FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
- FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
+ FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
}
}
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
} else {
- if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
/* dst may be the same as src1 or src2. */
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
}
- if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
- FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
- if (!(op & SLJIT_SET_C))
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+ if (!is_carry)
return SLJIT_SUCCESS;
- /* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
- FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+ /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
/* Set carry flag. */
- return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
+ return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
case SLJIT_SUB:
- if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
src2 = TMP_REG2;
flags &= ~SRC2_IMM;
}
+ is_handled = 0;
+
if (flags & SRC2_IMM) {
- if (op & SLJIT_SET_O) {
- if (src2 >= 0)
- FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- else
- FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+ is_handled = 1;
}
- if (op & SLJIT_SET_E)
+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
+ FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+ is_handled = 1;
+ }
+ }
+
+ if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
+ is_handled = 1;
+
+ if (flags & SRC2_IMM) {
+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
+ }
+ else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)
+ {
+ FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+ }
+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
+ FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
+ }
+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)
+ {
+ FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+ }
+ }
+
+ if (is_handled) {
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
+ if (!(flags & UNUSED_DEST))
+ return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));
+ }
+ else {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ if (!(flags & UNUSED_DEST))
+ return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
+ if (flags & SRC2_IMM) {
+ if (is_overflow) {
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ else
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ }
+ else if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
- if (op & (SLJIT_SET_C | SLJIT_SET_O))
- FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
/* dst may be the same as src1 or src2. */
- if (CHECK_FLAGS(SLJIT_SET_E))
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
}
else {
- if (op & SLJIT_SET_O)
- FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- if (op & SLJIT_SET_E)
+ if (is_overflow)
+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ else if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
- if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
- FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
- if (op & SLJIT_SET_U)
- FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
- if (op & SLJIT_SET_S) {
- FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
- FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
- }
+
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
/* dst may be the same as src1 or src2. */
- if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
}
- if (!(op & SLJIT_SET_O))
+ if (!is_overflow)
return SLJIT_SUCCESS;
- FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
- FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
- return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
case SLJIT_SUBC:
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
@@ -369,28 +434,31 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
flags &= ~SRC2_IMM;
}
+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
if (flags & SRC2_IMM) {
- if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
/* dst may be the same as src1 or src2. */
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
}
else {
- if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
/* dst may be the same as src1 or src2. */
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
}
- if (op & SLJIT_SET_C)
- FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG));
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
- FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
- return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+ return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;
case SLJIT_MUL:
SLJIT_ASSERT(!(flags & SRC2_IMM));
- if (!(op & SLJIT_SET_O)) {
+
+ if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
if (op & SLJIT_I32_OP)
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
@@ -402,10 +470,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
#endif
}
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
- FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG));
+ FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
- FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG));
- return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
+ return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
case SLJIT_AND:
EMIT_LOGICAL(ANDI, AND);
@@ -432,7 +500,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return SLJIT_SUCCESS;
}
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
}
@@ -446,24 +514,26 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
- sljit_ins *inst = (sljit_ins*)addr;
+ sljit_ins *inst = (sljit_ins *)addr;
- inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
- inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
- inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
- inst[5] = (inst[5] & 0xffff0000) | (new_addr & 0xffff);
+ inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
+ inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
+ inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
+ inst[5] = (inst[5] & 0xffff0000) | (new_target & 0xffff);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 6);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_ins *inst = (sljit_ins*)addr;
+ sljit_ins *inst = (sljit_ins *)addr;
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 6);
}
diff --git a/pcre/sljit/sljitNativeMIPS_common.c b/pcre/sljit/sljitNativeMIPS_common.c
index 3d58bb5ee4c..ee207fe1191 100644
--- a/pcre/sljit/sljitNativeMIPS_common.c
+++ b/pcre/sljit/sljitNativeMIPS_common.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -57,19 +57,14 @@ typedef sljit_u32 sljit_ins;
#define RETURN_ADDR_REG 31
/* Flags are kept in volatile registers. */
-#define EQUAL_FLAG 12
-/* And carry flag as well. */
-#define ULESS_FLAG 13
-#define UGREATER_FLAG 14
-#define LESS_FLAG 15
-#define GREATER_FLAG 31
-#define OVERFLOW_FLAG 1
+#define EQUAL_FLAG 31
+#define OTHER_FLAG 1
#define TMP_FREG1 (0)
#define TMP_FREG2 ((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) << 1)
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
- 0, 2, 5, 6, 7, 8, 9, 10, 11, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 3, 25, 4
+ 0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 3, 25, 4
};
/* --------------------------------------------------------------------- */
@@ -178,7 +173,13 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
#define CLZ (HI(28) | LO(32))
#define DCLZ (HI(28) | LO(36))
+#define MOVF (HI(0) | (0 << 16) | LO(1))
+#define MOVN (HI(0) | LO(11))
+#define MOVT (HI(0) | (1 << 16) | LO(1))
+#define MOVZ (HI(0) | LO(10))
#define MUL (HI(28) | LO(2))
+#define PREF (HI(51))
+#define PREFX (HI(19) | LO(15))
#define SEB (HI(31) | (16 << 6) | LO(32))
#define SEH (HI(31) | (24 << 6) | LO(32))
#endif
@@ -218,7 +219,7 @@ static SLJIT_INLINE sljit_ins invert_branch(sljit_s32 flags)
return (flags & IS_BIT26_COND) ? (1 << 26) : (1 << 16);
}
-static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
{
sljit_sw diff;
sljit_uw target_addr;
@@ -237,9 +238,10 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
target_addr = jump->u.target;
else {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- target_addr = (sljit_uw)(code + jump->u.label->size);
+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
}
- inst = (sljit_ins*)jump->addr;
+
+ inst = (sljit_ins *)jump->addr;
if (jump->flags & IS_COND)
inst--;
@@ -250,7 +252,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
/* B instructions. */
if (jump->flags & IS_MOVABLE) {
- diff = ((sljit_sw)target_addr - (sljit_sw)(inst)) >> 2;
+ diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
jump->flags |= PATCH_B;
@@ -268,7 +270,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
}
}
else {
- diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1)) >> 2;
+ diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
jump->flags |= PATCH_B;
@@ -364,6 +366,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_sw executable_offset;
sljit_uw addr;
struct sljit_label *label;
@@ -380,9 +383,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ executable_offset = SLJIT_EXEC_OFFSET(code);
+
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+
do {
buf_ptr = (sljit_ins*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 2);
@@ -393,8 +399,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
/* These structures are ordered by their address. */
if (label && label->size == word_count) {
- /* Just recording the address. */
- label->addr = (sljit_uw)code_ptr;
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = code_ptr - code;
label = label->next;
}
@@ -404,7 +409,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#else
jump->addr = (sljit_uw)(code_ptr - 7);
#endif
- code_ptr = detect_jump_type(jump, code_ptr, code);
+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
jump = jump->next;
}
if (const_ && const_->addr == word_count) {
@@ -434,16 +439,16 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
while (jump) {
do {
addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
- buf_ptr = (sljit_ins*)jump->addr;
+ buf_ptr = (sljit_ins *)jump->addr;
if (jump->flags & PATCH_B) {
- addr = (sljit_sw)(addr - (jump->addr + sizeof(sljit_ins))) >> 2;
+ addr = (sljit_sw)(addr - ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins))) >> 2;
SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | (addr & 0xffff);
break;
}
if (jump->flags & PATCH_J) {
- SLJIT_ASSERT((addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff));
+ SLJIT_ASSERT((addr & ~0xfffffff) == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~0xfffffff));
buf_ptr[0] |= (addr >> 2) & 0x03ffffff;
break;
}
@@ -476,8 +481,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
}
compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
- SLJIT_ENABLE_EXEC(code, code_ptr);
+
+ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
#ifndef __GNUC__
SLJIT_CACHE_FLUSH(code, code_ptr);
#else
@@ -487,6 +496,31 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
return code;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#elif defined(__GNUC__)
+ sljit_sw fir;
+ asm ("cfc1 %0, $0" : "=r"(fir));
+ return (fir >> 22) & 0x1;
+#else
+#error "FIR check is not implemented for this architecture"
+#endif
+
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_CMOV:
+ return 1;
+#endif
+
+ default:
+ return 0;
+ }
+}
+
/* --------------------------------------------------------------------- */
/* Entry, exit */
/* --------------------------------------------------------------------- */
@@ -521,10 +555,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#define SLOW_SRC2 0x20000
#define SLOW_DEST 0x40000
-/* Only these flags are set. UNUSED_DEST is not set when no flags should be set. */
-#define CHECK_FLAGS(list) \
- (!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list))))
-
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#define STACK_STORE SW
#define STACK_LOAD LW
@@ -760,34 +790,28 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
base = arg & REG_MASK;
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
- argw &= 0x3;
- if ((flags & WRITE_BACK) && reg_ar == DR(base)) {
- SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar);
- FAIL_IF(push_inst(compiler, ADDU_W | SA(reg_ar) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
- reg_ar = DR(TMP_REG1);
+ if (SLJIT_UNLIKELY(flags & WRITE_BACK)) {
+ SLJIT_ASSERT(argw == 0);
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | D(base), DR(base)));
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
}
+ argw &= 0x3;
+
/* Using the cache. */
if (argw == compiler->cache_argw) {
- if (!(flags & WRITE_BACK)) {
- if (arg == compiler->cache_arg)
+ if (arg == compiler->cache_arg)
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
+
+ if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
+ if (arg == next_arg && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = arg;
+ compiler->cache_argw = argw;
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
- if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
- if (arg == next_arg && argw == (next_argw & 0x3)) {
- compiler->cache_arg = arg;
- compiler->cache_argw = argw;
- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
- }
- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
- }
- }
- else {
- if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
}
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
}
}
@@ -797,35 +821,18 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
}
- if (!(flags & WRITE_BACK)) {
- if (arg == next_arg && argw == (next_argw & 0x3)) {
- compiler->cache_arg = arg;
- compiler->cache_argw = argw;
- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
- tmp_ar = DR(TMP_REG3);
- }
- else
- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
+ if (arg == next_arg && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = arg;
+ compiler->cache_argw = argw;
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
+ tmp_ar = DR(TMP_REG3);
}
- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(base), DR(base)));
- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
+ else
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
}
if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) {
- /* Update only applies if a base register exists. */
- if (reg_ar == DR(base)) {
- SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar);
- if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
- FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar) | IMM(argw), MOVABLE_INS));
- if (argw)
- return push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base));
- return SLJIT_SUCCESS;
- }
- FAIL_IF(push_inst(compiler, ADDU_W | SA(reg_ar) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
- reg_ar = DR(TMP_REG1);
- }
-
if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
if (argw)
FAIL_IF(push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base)));
@@ -915,10 +922,8 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
}
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
- if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM))
- return SLJIT_SUCCESS;
- if (GET_FLAGS(op))
- flags |= UNUSED_DEST;
+ SLJIT_ASSERT(HAS_FLAGS(op));
+ flags |= UNUSED_DEST;
}
else if (FAST_IS_REG(dst)) {
dst_r = dst;
@@ -1080,6 +1085,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ if (!(src & OFFS_REG_MASK)) {
+ if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)
+ return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);
+
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
+ return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
+ }
+
+ srcw &= 0x3;
+
+ if (SLJIT_UNLIKELY(srcw != 0)) {
+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));
+ return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
+ }
+
+ return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);
+}
+#endif
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
@@ -1095,6 +1123,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+ if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
+ return emit_prefetch(compiler, src, srcw);
+#endif
+ return SLJIT_SUCCESS;
+ }
+
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT) {
flags |= INT_DATA | SIGNED_DATA;
@@ -1198,6 +1234,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+ return SLJIT_SUCCESS;
+
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
if (op & SLJIT_I32_OP) {
flags |= INT_DATA | SIGNED_DATA;
@@ -1274,19 +1313,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
- return SLJIT_IS_FPU_AVAILABLE;
-#elif defined(__GNUC__)
- sljit_sw fir;
- asm ("cfc1 %0, $0" : "=r"(fir));
- return (fir >> 22) & 0x1;
-#else
-#error "FIR check is not implemented for this architecture"
-#endif
-}
-
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))
#define FMT(op) (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) << (21 - 8))
@@ -1309,9 +1335,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
if (FAST_IS_REG(dst))
return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);
@@ -1365,6 +1388,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
+ sljit_ins inst;
+
if (src1 & SLJIT_MEM) {
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
src1 = TMP_FREG1;
@@ -1379,25 +1404,26 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
else
src2 <<= 1;
- /* src2 and src1 are swapped. */
- if (op & SLJIT_SET_E) {
- FAIL_IF(push_inst(compiler, C_UEQ_S | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS));
- FAIL_IF(push_inst(compiler, CFC1 | TA(EQUAL_FLAG) | DA(FCSR_REG), EQUAL_FLAG));
- FAIL_IF(push_inst(compiler, SRL | TA(EQUAL_FLAG) | DA(EQUAL_FLAG) | SH_IMM(23), EQUAL_FLAG));
- FAIL_IF(push_inst(compiler, ANDI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG));
+ switch (GET_FLAG_TYPE(op)) {
+ case SLJIT_EQUAL_F64:
+ case SLJIT_NOT_EQUAL_F64:
+ inst = C_UEQ_S;
+ break;
+ case SLJIT_LESS_F64:
+ case SLJIT_GREATER_EQUAL_F64:
+ inst = C_ULT_S;
+ break;
+ case SLJIT_GREATER_F64:
+ case SLJIT_LESS_EQUAL_F64:
+ inst = C_ULE_S;
+ break;
+ default:
+ SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED_F64 || GET_FLAG_TYPE(op) == SLJIT_ORDERED_F64);
+ inst = C_UN_S;
+ break;
}
- if (op & SLJIT_SET_S) {
- /* Mixing the instructions for the two checks. */
- FAIL_IF(push_inst(compiler, C_ULT_S | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS));
- FAIL_IF(push_inst(compiler, CFC1 | TA(ULESS_FLAG) | DA(FCSR_REG), ULESS_FLAG));
- FAIL_IF(push_inst(compiler, C_ULT_S | FMT(op) | FT(src1) | FS(src2), UNMOVABLE_INS));
- FAIL_IF(push_inst(compiler, SRL | TA(ULESS_FLAG) | DA(ULESS_FLAG) | SH_IMM(23), ULESS_FLAG));
- FAIL_IF(push_inst(compiler, ANDI | SA(ULESS_FLAG) | TA(ULESS_FLAG) | IMM(1), ULESS_FLAG));
- FAIL_IF(push_inst(compiler, CFC1 | TA(UGREATER_FLAG) | DA(FCSR_REG), UGREATER_FLAG));
- FAIL_IF(push_inst(compiler, SRL | TA(UGREATER_FLAG) | DA(UGREATER_FLAG) | SH_IMM(23), UGREATER_FLAG));
- FAIL_IF(push_inst(compiler, ANDI | SA(UGREATER_FLAG) | TA(UGREATER_FLAG) | IMM(1), UGREATER_FLAG));
- }
- return push_inst(compiler, C_UN_S | FMT(op) | FT(src2) | FS(src1), FCSR_FCC);
+
+ return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
@@ -1543,10 +1569,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
- /* For UNUSED dst. Uncommon, but possible. */
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
if (FAST_IS_REG(dst))
return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst));
@@ -1626,7 +1648,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
sljit_s32 delay_check = UNMOVABLE_INS;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
CHECK_PTR(check_sljit_emit_jump(compiler, type));
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -1636,55 +1657,39 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
switch (type) {
case SLJIT_EQUAL:
- case SLJIT_NOT_EQUAL_F64:
BR_NZ(EQUAL_FLAG);
break;
case SLJIT_NOT_EQUAL:
- case SLJIT_EQUAL_F64:
BR_Z(EQUAL_FLAG);
break;
case SLJIT_LESS:
- case SLJIT_LESS_F64:
- BR_Z(ULESS_FLAG);
- break;
- case SLJIT_GREATER_EQUAL:
- case SLJIT_GREATER_EQUAL_F64:
- BR_NZ(ULESS_FLAG);
- break;
case SLJIT_GREATER:
- case SLJIT_GREATER_F64:
- BR_Z(UGREATER_FLAG);
- break;
- case SLJIT_LESS_EQUAL:
- case SLJIT_LESS_EQUAL_F64:
- BR_NZ(UGREATER_FLAG);
- break;
case SLJIT_SIG_LESS:
- BR_Z(LESS_FLAG);
- break;
- case SLJIT_SIG_GREATER_EQUAL:
- BR_NZ(LESS_FLAG);
- break;
case SLJIT_SIG_GREATER:
- BR_Z(GREATER_FLAG);
- break;
- case SLJIT_SIG_LESS_EQUAL:
- BR_NZ(GREATER_FLAG);
- break;
case SLJIT_OVERFLOW:
case SLJIT_MUL_OVERFLOW:
- BR_Z(OVERFLOW_FLAG);
+ BR_Z(OTHER_FLAG);
break;
+ case SLJIT_GREATER_EQUAL:
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_SIG_GREATER_EQUAL:
+ case SLJIT_SIG_LESS_EQUAL:
case SLJIT_NOT_OVERFLOW:
case SLJIT_MUL_NOT_OVERFLOW:
- BR_NZ(OVERFLOW_FLAG);
- break;
- case SLJIT_UNORDERED_F64:
- BR_F();
+ BR_NZ(OTHER_FLAG);
break;
+ case SLJIT_NOT_EQUAL_F64:
+ case SLJIT_GREATER_EQUAL_F64:
+ case SLJIT_GREATER_F64:
case SLJIT_ORDERED_F64:
BR_T();
break;
+ case SLJIT_EQUAL_F64:
+ case SLJIT_LESS_F64:
+ case SLJIT_LESS_EQUAL_F64:
+ case SLJIT_UNORDERED_F64:
+ BR_F();
+ break;
default:
/* Not conditional branch. */
inst = 0;
@@ -1744,7 +1749,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
sljit_ins inst;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
@@ -1857,87 +1861,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
#undef RESOLVE_IMM1
#undef RESOLVE_IMM2
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
- sljit_s32 src1, sljit_sw src1w,
- sljit_s32 src2, sljit_sw src2w)
-{
- struct sljit_jump *jump;
- sljit_ins inst;
- sljit_s32 if_true;
-
- CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
- CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));
-
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
-
- if (src1 & SLJIT_MEM) {
- PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
- src1 = TMP_FREG1;
- }
- else
- src1 <<= 1;
-
- if (src2 & SLJIT_MEM) {
- PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
- src2 = TMP_FREG2;
- }
- else
- src2 <<= 1;
-
- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
- PTR_FAIL_IF(!jump);
- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
- jump->flags |= IS_BIT16_COND;
-
- switch (type & 0xff) {
- case SLJIT_EQUAL_F64:
- inst = C_UEQ_S;
- if_true = 1;
- break;
- case SLJIT_NOT_EQUAL_F64:
- inst = C_UEQ_S;
- if_true = 0;
- break;
- case SLJIT_LESS_F64:
- inst = C_ULT_S;
- if_true = 1;
- break;
- case SLJIT_GREATER_EQUAL_F64:
- inst = C_ULT_S;
- if_true = 0;
- break;
- case SLJIT_GREATER_F64:
- inst = C_ULE_S;
- if_true = 0;
- break;
- case SLJIT_LESS_EQUAL_F64:
- inst = C_ULE_S;
- if_true = 1;
- break;
- case SLJIT_UNORDERED_F64:
- inst = C_UN_S;
- if_true = 1;
- break;
- default: /* Make compilers happy. */
- SLJIT_ASSERT_STOP();
- case SLJIT_ORDERED_F64:
- inst = C_UN_S;
- if_true = 0;
- break;
- }
-
- PTR_FAIL_IF(push_inst(compiler, inst | FMT(type) | FT(src2) | FS(src1), UNMOVABLE_INS));
- /* Intentionally the other opcode. */
- PTR_FAIL_IF(push_inst(compiler, (if_true ? BC1F : BC1T) | JUMP_LENGTH, UNMOVABLE_INS));
- PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
- PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
- jump->addr = compiler->size;
- PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
- return jump;
-}
-
#undef JUMP_LENGTH
#undef BR_Z
#undef BR_NZ
@@ -2007,115 +1930,160 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src, sljit_sw srcw,
sljit_s32 type)
{
- sljit_s32 sugg_dst_ar, dst_ar;
- sljit_s32 flags = GET_ALL_FLAGS(op);
+ sljit_s32 src_ar, dst_ar;
+ sljit_s32 saved_op = op;
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-# define mem_type WORD_DATA
+ sljit_s32 mem_type = WORD_DATA;
#else
sljit_s32 mem_type = (op & SLJIT_I32_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
#endif
CHECK_ERROR();
- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
op = GET_OPCODE(op);
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
- if (op == SLJIT_MOV_S32 || op == SLJIT_MOV_U32)
+ if (op == SLJIT_MOV_S32)
mem_type = INT_DATA | SIGNED_DATA;
#endif
- sugg_dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
+ dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
- ADJUST_LOCAL_OFFSET(src, srcw);
- FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));
- src = TMP_REG1;
- srcw = 0;
- }
+
+ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
+ FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));
switch (type & 0xff) {
case SLJIT_EQUAL:
case SLJIT_NOT_EQUAL:
- FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
- dst_ar = sugg_dst_ar;
- break;
- case SLJIT_LESS:
- case SLJIT_GREATER_EQUAL:
- case SLJIT_LESS_F64:
- case SLJIT_GREATER_EQUAL_F64:
- dst_ar = ULESS_FLAG;
- break;
- case SLJIT_GREATER:
- case SLJIT_LESS_EQUAL:
- case SLJIT_GREATER_F64:
- case SLJIT_LESS_EQUAL_F64:
- dst_ar = UGREATER_FLAG;
- break;
- case SLJIT_SIG_LESS:
- case SLJIT_SIG_GREATER_EQUAL:
- dst_ar = LESS_FLAG;
- break;
- case SLJIT_SIG_GREATER:
- case SLJIT_SIG_LESS_EQUAL:
- dst_ar = GREATER_FLAG;
- break;
- case SLJIT_OVERFLOW:
- case SLJIT_NOT_OVERFLOW:
- dst_ar = OVERFLOW_FLAG;
+ FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
+ src_ar = dst_ar;
break;
case SLJIT_MUL_OVERFLOW:
case SLJIT_MUL_NOT_OVERFLOW:
- FAIL_IF(push_inst(compiler, SLTIU | SA(OVERFLOW_FLAG) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
- dst_ar = sugg_dst_ar;
+ FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
+ src_ar = dst_ar;
type ^= 0x1; /* Flip type bit for the XORI below. */
break;
+ case SLJIT_GREATER_F64:
+ case SLJIT_LESS_EQUAL_F64:
+ type ^= 0x1; /* Flip type bit for the XORI below. */
case SLJIT_EQUAL_F64:
case SLJIT_NOT_EQUAL_F64:
- dst_ar = EQUAL_FLAG;
- break;
-
+ case SLJIT_LESS_F64:
+ case SLJIT_GREATER_EQUAL_F64:
case SLJIT_UNORDERED_F64:
case SLJIT_ORDERED_F64:
- FAIL_IF(push_inst(compiler, CFC1 | TA(sugg_dst_ar) | DA(FCSR_REG), sugg_dst_ar));
- FAIL_IF(push_inst(compiler, SRL | TA(sugg_dst_ar) | DA(sugg_dst_ar) | SH_IMM(23), sugg_dst_ar));
- FAIL_IF(push_inst(compiler, ANDI | SA(sugg_dst_ar) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
- dst_ar = sugg_dst_ar;
+ FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));
+ FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));
+ FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));
+ src_ar = dst_ar;
break;
default:
- SLJIT_ASSERT_STOP();
- dst_ar = sugg_dst_ar;
+ src_ar = OTHER_FLAG;
break;
}
if (type & 0x1) {
- FAIL_IF(push_inst(compiler, XORI | SA(dst_ar) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
- dst_ar = sugg_dst_ar;
+ FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));
+ src_ar = dst_ar;
}
- if (op >= SLJIT_ADD) {
- if (DR(TMP_REG2) != dst_ar)
- FAIL_IF(push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
- return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
+ if (op < SLJIT_ADD) {
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);
+
+ if (src_ar != dst_ar)
+ return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);
+ return SLJIT_SUCCESS;
}
+ /* OTHER_FLAG cannot be specified as src2 argument at the moment. */
+ if (DR(TMP_REG2) != src_ar)
+ FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
+
+ mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;
+
if (dst & SLJIT_MEM)
- return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw);
+ return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
+ return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);
+}
- if (sugg_dst_ar != dst_ar)
- return push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | DA(sugg_dst_ar), sugg_dst_ar);
- return SLJIT_SUCCESS;
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+ sljit_ins ins;
+#endif
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-# undef mem_type
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+
+ if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (dst_reg & SLJIT_I32_OP)
+ srcw = (sljit_s32)srcw;
+#endif
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ dst_reg &= ~SLJIT_I32_OP;
+
+ switch (type & 0xff) {
+ case SLJIT_EQUAL:
+ ins = MOVZ | TA(EQUAL_FLAG);
+ break;
+ case SLJIT_NOT_EQUAL:
+ ins = MOVN | TA(EQUAL_FLAG);
+ break;
+ case SLJIT_LESS:
+ case SLJIT_GREATER:
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_GREATER:
+ case SLJIT_OVERFLOW:
+ case SLJIT_MUL_OVERFLOW:
+ ins = MOVN | TA(OTHER_FLAG);
+ break;
+ case SLJIT_GREATER_EQUAL:
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_SIG_GREATER_EQUAL:
+ case SLJIT_SIG_LESS_EQUAL:
+ case SLJIT_NOT_OVERFLOW:
+ case SLJIT_MUL_NOT_OVERFLOW:
+ ins = MOVZ | TA(OTHER_FLAG);
+ break;
+ case SLJIT_EQUAL_F64:
+ case SLJIT_LESS_F64:
+ case SLJIT_LESS_EQUAL_F64:
+ case SLJIT_UNORDERED_F64:
+ ins = MOVT;
+ break;
+ case SLJIT_NOT_EQUAL_F64:
+ case SLJIT_GREATER_EQUAL_F64:
+ case SLJIT_GREATER_F64:
+ case SLJIT_ORDERED_F64:
+ ins = MOVF;
+ break;
+ default:
+ ins = MOVZ | TA(OTHER_FLAG);
+ SLJIT_UNREACHABLE();
+ break;
+ }
+
+ return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg));
+
+#else
+ return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
#endif
}
@@ -2125,7 +2093,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
sljit_s32 reg;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(1);
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
@@ -2133,7 +2100,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+ reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
diff --git a/pcre/sljit/sljitNativePPC_32.c b/pcre/sljit/sljitNativePPC_32.c
index 0f23cf86ddc..fc185f78475 100644
--- a/pcre/sljit/sljitNativePPC_32.c
+++ b/pcre/sljit/sljitNativePPC_32.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -88,77 +88,86 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
case SLJIT_NEG:
SLJIT_ASSERT(src1 == TMP_REG1);
- return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
+ /* Setting XER SO is not enough, CR SO is also needed. */
+ return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
- return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
+ return push_inst(compiler, CNTLZW | S(src2) | A(dst));
case SLJIT_ADD:
if (flags & ALT_FORM1) {
- /* Flags does not set: BIN_IMM_EXTS unnecessary. */
- SLJIT_ASSERT(src2 == TMP_REG2);
- return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
+ /* Setting XER SO is not enough, CR SO is also needed. */
+ return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
}
+
if (flags & ALT_FORM2) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
SLJIT_ASSERT(src2 == TMP_REG2);
- return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+
+ if (flags & ALT_FORM3)
+ return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+
+ if (flags & ALT_FORM4) {
+ FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));
+ src1 = dst;
+ }
+
+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));
}
if (flags & ALT_FORM3) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
}
- if (flags & ALT_FORM4) {
- /* Flags does not set: BIN_IMM_EXTS unnecessary. */
- FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
- return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
- }
if (!(flags & ALT_SET_FLAGS))
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
- return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+ if (flags & ALT_FORM4)
+ return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+ return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
case SLJIT_ADDC:
- if (flags & ALT_FORM1) {
- FAIL_IF(push_inst(compiler, MFXER | D(0)));
- FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
- return push_inst(compiler, MTXER | S(0));
- }
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
case SLJIT_SUB:
if (flags & ALT_FORM1) {
+ if (flags & ALT_FORM2) {
+ FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));
+ if (!(flags & ALT_FORM3))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
+ }
+ FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));
+ if (!(flags & ALT_FORM3))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+ }
+
+ if (flags & ALT_FORM2) {
+ /* Setting XER SO is not enough, CR SO is also needed. */
+ return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ }
+
+ if (flags & ALT_FORM3) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
}
- if (flags & (ALT_FORM2 | ALT_FORM3)) {
- SLJIT_ASSERT(src2 == TMP_REG2);
- if (flags & ALT_FORM2)
- FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
- if (flags & ALT_FORM3)
- return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm);
- return SLJIT_SUCCESS;
- }
- if (flags & (ALT_FORM4 | ALT_FORM5)) {
- if (flags & ALT_FORM4)
- FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
- if (flags & ALT_FORM5)
- FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
- return SLJIT_SUCCESS;
+
+ if (flags & ALT_FORM4) {
+ if (flags & ALT_FORM5) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm);
+ }
+ return push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2));
}
+
if (!(flags & ALT_SET_FLAGS))
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
- if (flags & ALT_FORM6)
- FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
- return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ if (flags & ALT_FORM5)
+ return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));
case SLJIT_SUBC:
- if (flags & ALT_FORM1) {
- FAIL_IF(push_inst(compiler, MFXER | D(0)));
- FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
- return push_inst(compiler, MTXER | S(0));
- }
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
case SLJIT_MUL:
@@ -166,7 +175,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
}
- return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
case SLJIT_AND:
if (flags & ALT_FORM1) {
@@ -228,19 +237,15 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_ASHR:
- if (flags & ALT_FORM3)
- FAIL_IF(push_inst(compiler, MFXER | D(0)));
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
compiler->imm &= 0x1f;
- FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
+ return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
}
- else
- FAIL_IF(push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)));
- return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
+ return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
}
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
}
@@ -250,20 +255,22 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
- sljit_ins *inst = (sljit_ins*)addr;
+ sljit_ins *inst = (sljit_ins *)addr;
- inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
- inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
+ inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
+ inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_ins *inst = (sljit_ins*)addr;
+ sljit_ins *inst = (sljit_ins *)addr;
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
diff --git a/pcre/sljit/sljitNativePPC_64.c b/pcre/sljit/sljitNativePPC_64.c
index 8e3223f7251..5366c30d90c 100644
--- a/pcre/sljit/sljitNativePPC_64.c
+++ b/pcre/sljit/sljitNativePPC_64.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -204,84 +204,118 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
case SLJIT_NEG:
SLJIT_ASSERT(src1 == TMP_REG1);
+
+ if ((flags & (ALT_FORM1 | ALT_SIGN_EXT)) == (ALT_FORM1 | ALT_SIGN_EXT)) {
+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
+ FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(TMP_REG2)));
+ return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
+ }
+
UN_EXTS();
- return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
+ /* Setting XER SO is not enough, CR SO is also needed. */
+ return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
if (flags & ALT_FORM1)
- return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
- return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst));
+ return push_inst(compiler, CNTLZW | S(src2) | A(dst));
+ return push_inst(compiler, CNTLZD | S(src2) | A(dst));
case SLJIT_ADD:
if (flags & ALT_FORM1) {
- /* Flags does not set: BIN_IMM_EXTS unnecessary. */
- SLJIT_ASSERT(src2 == TMP_REG2);
- return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
+ if (flags & ALT_SIGN_EXT) {
+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
+ src1 = TMP_REG1;
+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
+ src2 = TMP_REG2;
+ }
+ /* Setting XER SO is not enough, CR SO is also needed. */
+ FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)));
+ if (flags & ALT_SIGN_EXT)
+ return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
+ return SLJIT_SUCCESS;
}
+
if (flags & ALT_FORM2) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
SLJIT_ASSERT(src2 == TMP_REG2);
- return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+
+ if (flags & ALT_FORM3)
+ return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+
+ if (flags & ALT_FORM4) {
+ FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));
+ src1 = dst;
+ }
+
+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));
}
if (flags & ALT_FORM3) {
SLJIT_ASSERT(src2 == TMP_REG2);
BIN_IMM_EXTS();
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
}
- if (flags & ALT_FORM4) {
- /* Flags does not set: BIN_IMM_EXTS unnecessary. */
- FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
- return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
- }
if (!(flags & ALT_SET_FLAGS))
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
BIN_EXTS();
- return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+ if (flags & ALT_FORM4)
+ return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+ return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
case SLJIT_ADDC:
- if (flags & ALT_FORM1) {
- FAIL_IF(push_inst(compiler, MFXER | D(0)));
- FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
- return push_inst(compiler, MTXER | S(0));
- }
BIN_EXTS();
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
case SLJIT_SUB:
if (flags & ALT_FORM1) {
+ if (flags & ALT_FORM2) {
+ FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
+ if (!(flags & ALT_FORM3))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
+ }
+ FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
+ if (!(flags & ALT_FORM3))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+ }
+
+ if (flags & ALT_FORM2) {
+ if (flags & ALT_SIGN_EXT) {
+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
+ src1 = TMP_REG1;
+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
+ src2 = TMP_REG2;
+ }
+ /* Setting XER SO is not enough, CR SO is also needed. */
+ FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));
+ if (flags & ALT_SIGN_EXT)
+ return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
+ return SLJIT_SUCCESS;
+ }
+
+ if (flags & ALT_FORM3) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
}
- if (flags & (ALT_FORM2 | ALT_FORM3)) {
- SLJIT_ASSERT(src2 == TMP_REG2);
- if (flags & ALT_FORM2)
- FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
- if (flags & ALT_FORM3)
- return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
- return SLJIT_SUCCESS;
- }
- if (flags & (ALT_FORM4 | ALT_FORM5)) {
- if (flags & ALT_FORM4)
- FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
- if (flags & ALT_FORM5)
- return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
- return SLJIT_SUCCESS;
+
+ if (flags & ALT_FORM4) {
+ if (flags & ALT_FORM5) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
+ }
+ return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
}
+
if (!(flags & ALT_SET_FLAGS))
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
BIN_EXTS();
- if (flags & ALT_FORM6)
- FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
- return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ if (flags & ALT_FORM5)
+ return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));
case SLJIT_SUBC:
- if (flags & ALT_FORM1) {
- FAIL_IF(push_inst(compiler, MFXER | D(0)));
- FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
- return push_inst(compiler, MTXER | S(0));
- }
BIN_EXTS();
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
@@ -292,8 +326,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
}
BIN_EXTS();
if (flags & ALT_FORM2)
- return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
- return push_inst(compiler, MULLD | OERC(flags) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
case SLJIT_AND:
if (flags & ALT_FORM1) {
@@ -345,10 +379,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
compiler->imm &= 0x1f;
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));
}
- else {
- compiler->imm &= 0x3f;
- return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));
- }
+ compiler->imm &= 0x3f;
+ return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));
}
return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
@@ -359,33 +391,25 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
compiler->imm &= 0x1f;
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));
}
- else {
- compiler->imm &= 0x3f;
- return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));
- }
+ compiler->imm &= 0x3f;
+ return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));
}
return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_ASHR:
- if (flags & ALT_FORM3)
- FAIL_IF(push_inst(compiler, MFXER | D(0)));
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
if (flags & ALT_FORM2) {
compiler->imm &= 0x1f;
- FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
- }
- else {
- compiler->imm &= 0x3f;
- FAIL_IF(push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)));
+ return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
}
+ compiler->imm &= 0x3f;
+ return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4));
}
- else
- FAIL_IF(push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)));
- return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
+ return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2));
}
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
}
@@ -398,18 +422,19 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_ins *inst = (sljit_ins*)addr;
- inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
- inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
- inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
- inst[4] = (inst[4] & 0xffff0000) | (new_addr & 0xffff);
+ inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
+ inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
+ inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
+ inst[4] = (inst[4] & 0xffff0000) | (new_target & 0xffff);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 5);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
sljit_ins *inst = (sljit_ins*)addr;
@@ -417,5 +442,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 5);
}
diff --git a/pcre/sljit/sljitNativePPC_common.c b/pcre/sljit/sljitNativePPC_common.c
index 8621f525e66..775c708f2f9 100644
--- a/pcre/sljit/sljitNativePPC_common.c
+++ b/pcre/sljit/sljitNativePPC_common.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -127,9 +127,9 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
/* Instruction bit sections.
OE and Rc flag (see ALT_SET_FLAGS). */
-#define OERC(flags) (((flags & ALT_SET_FLAGS) >> 10) | (flags & ALT_SET_FLAGS))
+#define OE(flags) ((flags) & ALT_SET_FLAGS)
/* Rc flag (see ALT_SET_FLAGS). */
-#define RC(flags) ((flags & ALT_SET_FLAGS) >> 10)
+#define RC(flags) (((flags) & ALT_SET_FLAGS) >> 10)
#define HI(opcode) ((opcode) << 26)
#define LO(opcode) ((opcode) << 1)
@@ -154,6 +154,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
#define CMPL (HI(31) | LO(32))
#define CMPLI (HI(10))
#define CROR (HI(19) | LO(449))
+#define DCBT (HI(31) | LO(278))
#define DIVD (HI(31) | LO(489))
#define DIVDU (HI(31) | LO(457))
#define DIVW (HI(31) | LO(491))
@@ -249,7 +250,7 @@ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
{
sljit_sw diff;
sljit_uw target_addr;
@@ -267,7 +268,7 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
target_addr = jump->u.target;
else {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- target_addr = (sljit_uw)(code + jump->u.label->size);
+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
}
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
@@ -275,7 +276,7 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
goto keep_address;
#endif
- diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr)) & ~0x3l;
+ diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l;
extra_jump_flags = 0;
if (jump->flags & IS_COND) {
@@ -296,6 +297,7 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
jump->flags |= PATCH_B | extra_jump_flags;
return 1;
}
+
if (target_addr <= 0x03ffffff) {
jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags;
return 1;
@@ -309,6 +311,7 @@ keep_address:
jump->flags |= PATCH_ABS32;
return 1;
}
+
if (target_addr <= 0x7fffffffffffl) {
jump->flags |= PATCH_ABS48;
return 1;
@@ -326,6 +329,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_sw executable_offset;
sljit_uw addr;
struct sljit_label *label;
@@ -349,9 +353,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ executable_offset = SLJIT_EXEC_OFFSET(code);
+
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+
do {
buf_ptr = (sljit_ins*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 2);
@@ -363,7 +370,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* These structures are ordered by their address. */
if (label && label->size == word_count) {
/* Just recording the address. */
- label->addr = (sljit_uw)code_ptr;
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = code_ptr - code;
label = label->next;
}
@@ -373,7 +380,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#else
jump->addr = (sljit_uw)(code_ptr - 6);
#endif
- if (detect_jump_type(jump, code_ptr, code)) {
+ if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
code_ptr[-3] = code_ptr[0];
code_ptr -= 3;
@@ -420,7 +427,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} while (buf);
if (label && label->size == word_count) {
- label->addr = (sljit_uw)code_ptr;
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = code_ptr - code;
label = label->next;
}
@@ -438,11 +445,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
while (jump) {
do {
addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
- buf_ptr = (sljit_ins*)jump->addr;
+ buf_ptr = (sljit_ins *)jump->addr;
+
if (jump->flags & PATCH_B) {
if (jump->flags & IS_COND) {
if (!(jump->flags & PATCH_ABS_B)) {
- addr = addr - jump->addr;
+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
*buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
}
@@ -453,7 +461,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
}
else {
if (!(jump->flags & PATCH_ABS_B)) {
- addr = addr - jump->addr;
+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
*buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
}
@@ -464,6 +472,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
}
break;
}
+
/* Set the fields of immediate loads. */
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
@@ -492,25 +501,50 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
}
compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
- SLJIT_ENABLE_EXEC(code, code_ptr);
- SLJIT_CACHE_FLUSH(code, code_ptr);
+
+ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
if (((sljit_sw)code_ptr) & 0x4)
code_ptr++;
- sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
- return code_ptr;
-#else
- sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
- return code_ptr;
#endif
+ sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
+#endif
+
+ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+ return code_ptr;
#else
return code;
#endif
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#else
+ /* Available by default. */
+ return 1;
+#endif
+
+ case SLJIT_HAS_PRE_UPDATE:
+ case SLJIT_HAS_CLZ:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
/* --------------------------------------------------------------------- */
/* Entry, exit */
/* --------------------------------------------------------------------- */
@@ -545,7 +579,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#define ALT_FORM3 0x040000
#define ALT_FORM4 0x080000
#define ALT_FORM5 0x100000
-#define ALT_FORM6 0x200000
/* Source and destination is register. */
#define REG_DEST 0x000001
@@ -560,7 +593,7 @@ ALT_SIGN_EXT 0x000200
ALT_SET_FLAGS 0x000400
ALT_FORM1 0x010000
...
-ALT_FORM6 0x200000 */
+ALT_FORM5 0x100000 */
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
#include "sljitNativePPC_32.c"
@@ -851,7 +884,7 @@ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 inp_
sljit_ins inst;
/* Should work when (arg & REG_MASK) == 0. */
- SLJIT_COMPILE_ASSERT(A(0) == 0, a0_must_be_0);
+ SLJIT_ASSERT(A(0) == 0);
SLJIT_ASSERT(arg & SLJIT_MEM);
if (arg & OFFS_REG_MASK) {
@@ -1006,10 +1039,6 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 inp_flags
#endif
if (inp_flags & WRITE_BACK) {
- if (arg == reg) {
- FAIL_IF(push_inst(compiler, OR | S(reg) | A(tmp_r) | B(reg)));
- reg = tmp_r;
- }
tmp_r = arg;
FAIL_IF(push_inst(compiler, ADDIS | D(arg) | A(arg) | IMM(high_short >> 16)));
}
@@ -1132,7 +1161,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
sljit_s32 src1_r;
sljit_s32 src2_r;
sljit_s32 sugg_src2_r = TMP_REG2;
- sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_SIGN_EXT | ALT_SET_FLAGS);
+ sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
if (!(input_flags & ALT_KEEP_CACHE)) {
compiler->cache_arg = 0;
@@ -1141,8 +1170,6 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
/* Destination check. */
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
- if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM))
- return SLJIT_SUCCESS;
dst_r = TMP_REG2;
}
else if (FAST_IS_REG(dst)) {
@@ -1295,6 +1322,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
+static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ if (!(src & OFFS_REG_MASK)) {
+ if (srcw == 0 && (src & REG_MASK) != SLJIT_UNUSED)
+ return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ /* Works with SLJIT_MEM0() case as well. */
+ return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
+ }
+
+ srcw &= 0x3;
+
+ if (srcw == 0)
+ return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | (srcw << 11) | ((31 - srcw) << 1)));
+#else
+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1)));
+#endif
+ return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
+}
+
#define EMIT_MOV(type, type_flags, type_cast) \
emit_op(compiler, (src & SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? type_cast srcw : srcw)
@@ -1302,7 +1354,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
- sljit_s32 flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
+ sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
sljit_s32 op_flags = GET_ALL_FLAGS(op);
CHECK_ERROR();
@@ -1310,11 +1362,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+ if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
+ return emit_prefetch(compiler, src, srcw);
+
+ return SLJIT_SUCCESS;
+ }
+
op = GET_OPCODE(op);
if ((src & SLJIT_IMM) && srcw == 0)
src = TMP_ZERO;
- if (op_flags & SLJIT_SET_O)
+ if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
if (op_flags & SLJIT_I32_OP) {
@@ -1340,6 +1399,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
flags |= INT_DATA | SIGNED_DATA;
if (src & SLJIT_IMM)
srcw = (sljit_s32)srcw;
+ if (HAS_FLAGS(op_flags))
+ flags |= ALT_SIGN_EXT;
}
#endif
}
@@ -1405,7 +1466,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_NEG:
- return emit_op(compiler, SLJIT_NEG, flags, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_NEG, flags | (GET_FLAG_TYPE(op_flags) ? ALT_FORM1 : 0), dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_CLZ:
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
@@ -1458,7 +1519,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- sljit_s32 flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
+ sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
CHECK_ERROR();
CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1466,6 +1527,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+ return SLJIT_SUCCESS;
+
if ((src1 & SLJIT_IMM) && src1w == 0)
src1 = TMP_ZERO;
if ((src2 & SLJIT_IMM) && src2w == 0)
@@ -1479,45 +1543,48 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
src1w = (sljit_s32)(src1w);
if (src2 & SLJIT_IMM)
src2w = (sljit_s32)(src2w);
- if (GET_FLAGS(op))
+ if (HAS_FLAGS(op))
flags |= ALT_SIGN_EXT;
}
#endif
- if (op & SLJIT_SET_O)
+ if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
if (src2 == TMP_REG2)
flags |= ALT_KEEP_CACHE;
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
- if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
+ if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
+
+ if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
if (TEST_SL_IMM(src2, src2w)) {
compiler->imm = src2w & 0xffff;
- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SL_IMM(src1, src1w)) {
compiler->imm = src1w & 0xffff;
- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
}
if (TEST_SH_IMM(src2, src2w)) {
compiler->imm = (src2w >> 16) & 0xffff;
- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SH_IMM(src1, src1w)) {
compiler->imm = (src1w >> 16) & 0xffff;
- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
}
/* Range between -1 and -32768 is covered above. */
if (TEST_ADD_IMM(src2, src2w)) {
compiler->imm = src2w & 0xffffffff;
- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_ADD_IMM(src1, src1w)) {
compiler->imm = src1w & 0xffffffff;
- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
- if (!(GET_FLAGS(op) & (SLJIT_SET_E | SLJIT_SET_O))) {
+ if (HAS_FLAGS(op)) {
if (TEST_SL_IMM(src2, src2w)) {
compiler->imm = src2w & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
@@ -1527,75 +1594,75 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
- return emit_op(compiler, SLJIT_ADD, flags, dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM4 : 0), dst, dstw, src1, src1w, src2, src2w);
case SLJIT_ADDC:
- return emit_op(compiler, SLJIT_ADDC, flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUB:
- if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
+ if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
+ if (dst == SLJIT_UNUSED) {
+ if (TEST_UL_IMM(src2, src2w)) {
+ compiler->imm = src2w & 0xffff;
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
+ compiler->imm = src2w;
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
+
+ if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
if (TEST_SL_IMM(src2, -src2w)) {
compiler->imm = (-src2w) & 0xffff;
- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SL_IMM(src1, src1w)) {
compiler->imm = src1w & 0xffff;
- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
}
if (TEST_SH_IMM(src2, -src2w)) {
compiler->imm = ((-src2w) >> 16) & 0xffff;
- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
/* Range between -1 and -32768 is covered above. */
if (TEST_ADD_IMM(src2, -src2w)) {
compiler->imm = -src2w & 0xffffffff;
- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
}
}
- if (dst == SLJIT_UNUSED && (op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S)) && !(op & (SLJIT_SET_O | SLJIT_SET_C))) {
- if (!(op & SLJIT_SET_U)) {
- /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
- if (TEST_SL_IMM(src2, src2w)) {
- compiler->imm = src2w & 0xffff;
- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
- }
- if (GET_FLAGS(op) == SLJIT_SET_E && TEST_SL_IMM(src1, src1w)) {
- compiler->imm = src1w & 0xffff;
- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
- }
+
+ if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) != GET_FLAG_TYPE(SLJIT_SET_CARRY)) {
+ if (TEST_SL_IMM(src2, src2w)) {
+ compiler->imm = src2w & 0xffff;
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
}
- if (!(op & (SLJIT_SET_E | SLJIT_SET_S))) {
- /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
- if (TEST_UL_IMM(src2, src2w)) {
- compiler->imm = src2w & 0xffff;
- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
- }
- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
- }
- if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= 0x7fff) {
- compiler->imm = src2w;
- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
- }
- return emit_op(compiler, SLJIT_SUB, flags | ((op & SLJIT_SET_U) ? ALT_FORM4 : 0) | ((op & (SLJIT_SET_E | SLJIT_SET_S)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
}
- if (!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O))) {
- if (TEST_SL_IMM(src2, -src2w)) {
- compiler->imm = (-src2w) & 0xffff;
- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
- }
+
+ if (TEST_SL_IMM(src2, -src2w)) {
+ compiler->imm = (-src2w) & 0xffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
/* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
- return emit_op(compiler, SLJIT_SUB, flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM6), dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUBC:
- return emit_op(compiler, SLJIT_SUBC, flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
+ return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_MUL:
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
if (op & SLJIT_I32_OP)
flags |= ALT_FORM2;
#endif
- if (!GET_FLAGS(op)) {
+ if (!HAS_FLAGS(op)) {
if (TEST_SL_IMM(src2, src2w)) {
compiler->imm = src2w & 0xffff;
return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
@@ -1605,13 +1672,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
+ else
+ FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_AND:
case SLJIT_OR:
case SLJIT_XOR:
/* Commutative unsigned operations. */
- if (!GET_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
+ if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
if (TEST_UL_IMM(src2, src2w)) {
compiler->imm = src2w;
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
@@ -1629,7 +1698,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
- if (!GET_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {
+ if (GET_OPCODE(op) != SLJIT_AND && GET_OPCODE(op) != SLJIT_AND) {
+ /* Unlike or and xor, and resets unwanted bits as well. */
if (TEST_UI_IMM(src2, src2w)) {
compiler->imm = src2w;
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
@@ -1641,12 +1711,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
}
return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
- case SLJIT_ASHR:
- if (op & SLJIT_KEEP_FLAGS)
- flags |= ALT_FORM3;
- /* Fall through. */
case SLJIT_SHL:
case SLJIT_LSHR:
+ case SLJIT_ASHR:
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
if (op & SLJIT_I32_OP)
flags |= ALT_FORM2;
@@ -1686,16 +1753,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
- return SLJIT_IS_FPU_AVAILABLE;
-#else
- /* Available by default. */
- return 1;
-#endif
-}
-
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 6))
#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
@@ -1728,9 +1785,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
op = GET_OPCODE(op);
FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
if (op == SLJIT_CONV_SW_FROM_F64) {
if (FAST_IS_REG(dst)) {
FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0));
@@ -1738,12 +1792,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
}
return emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, 0, 0);
}
-
#else
FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
-
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
#endif
if (FAST_IS_REG(dst)) {
@@ -2020,10 +2070,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
- /* For UNUSED dst. Uncommon, but possible. */
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
if (FAST_IS_REG(dst))
return push_inst(compiler, MFLR | D(dst));
@@ -2080,33 +2126,33 @@ static sljit_ins get_bo_bi_flags(sljit_s32 type)
return (4 << 21) | (2 << 16);
case SLJIT_LESS:
- case SLJIT_LESS_F64:
- return (12 << 21) | ((4 + 0) << 16);
-
- case SLJIT_GREATER_EQUAL:
- case SLJIT_GREATER_EQUAL_F64:
- return (4 << 21) | ((4 + 0) << 16);
-
- case SLJIT_GREATER:
- case SLJIT_GREATER_F64:
- return (12 << 21) | ((4 + 1) << 16);
-
- case SLJIT_LESS_EQUAL:
- case SLJIT_LESS_EQUAL_F64:
- return (4 << 21) | ((4 + 1) << 16);
-
case SLJIT_SIG_LESS:
return (12 << 21) | (0 << 16);
+ case SLJIT_GREATER_EQUAL:
case SLJIT_SIG_GREATER_EQUAL:
return (4 << 21) | (0 << 16);
+ case SLJIT_GREATER:
case SLJIT_SIG_GREATER:
return (12 << 21) | (1 << 16);
+ case SLJIT_LESS_EQUAL:
case SLJIT_SIG_LESS_EQUAL:
return (4 << 21) | (1 << 16);
+ case SLJIT_LESS_F64:
+ return (12 << 21) | ((4 + 0) << 16);
+
+ case SLJIT_GREATER_EQUAL_F64:
+ return (4 << 21) | ((4 + 0) << 16);
+
+ case SLJIT_GREATER_F64:
+ return (12 << 21) | ((4 + 1) << 16);
+
+ case SLJIT_LESS_EQUAL_F64:
+ return (4 << 21) | ((4 + 1) << 16);
+
case SLJIT_OVERFLOW:
case SLJIT_MUL_OVERFLOW:
return (12 << 21) | (3 << 16);
@@ -2139,7 +2185,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
sljit_ins bo_bi_flags;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
CHECK_PTR(check_sljit_emit_jump(compiler, type));
bo_bi_flags = get_bo_bi_flags(type & 0xff);
@@ -2209,153 +2254,148 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
}
-/* Get a bit from CR, all other bits are zeroed. */
-#define GET_CR_BIT(bit, dst) \
- FAIL_IF(push_inst(compiler, MFCR | D(dst))); \
- FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | ((1 + (bit)) << 11) | (31 << 6) | (31 << 1)));
-
-#define INVERT_BIT(dst) \
- FAIL_IF(push_inst(compiler, XORI | S(dst) | A(dst) | 0x1));
-
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src, sljit_sw srcw,
sljit_s32 type)
{
- sljit_s32 reg, input_flags;
- sljit_s32 flags = GET_ALL_FLAGS(op);
- sljit_sw original_dstw = dstw;
+ sljit_s32 reg, input_flags, cr_bit, invert;
+ sljit_s32 saved_op = op;
+ sljit_sw saved_dstw = dstw;
CHECK_ERROR();
- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ input_flags = (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA;
+#else
+ input_flags = WORD_DATA;
+#endif
op = GET_OPCODE(op);
reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
- ADJUST_LOCAL_OFFSET(src, srcw);
-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- input_flags = (flags & SLJIT_I32_OP) ? INT_DATA : WORD_DATA;
-#else
- input_flags = WORD_DATA;
-#endif
- FAIL_IF(emit_op_mem2(compiler, input_flags | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
- src = TMP_REG1;
- srcw = 0;
- }
+
+ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
+ FAIL_IF(emit_op_mem2(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));
+
+ invert = 0;
switch (type & 0xff) {
- case SLJIT_EQUAL:
- GET_CR_BIT(2, reg);
- break;
-
- case SLJIT_NOT_EQUAL:
- GET_CR_BIT(2, reg);
- INVERT_BIT(reg);
- break;
-
case SLJIT_LESS:
- case SLJIT_LESS_F64:
- GET_CR_BIT(4 + 0, reg);
+ case SLJIT_SIG_LESS:
+ cr_bit = 0;
break;
case SLJIT_GREATER_EQUAL:
- case SLJIT_GREATER_EQUAL_F64:
- GET_CR_BIT(4 + 0, reg);
- INVERT_BIT(reg);
+ case SLJIT_SIG_GREATER_EQUAL:
+ cr_bit = 0;
+ invert = 1;
break;
case SLJIT_GREATER:
- case SLJIT_GREATER_F64:
- GET_CR_BIT(4 + 1, reg);
+ case SLJIT_SIG_GREATER:
+ cr_bit = 1;
break;
case SLJIT_LESS_EQUAL:
- case SLJIT_LESS_EQUAL_F64:
- GET_CR_BIT(4 + 1, reg);
- INVERT_BIT(reg);
- break;
-
- case SLJIT_SIG_LESS:
- GET_CR_BIT(0, reg);
- break;
-
- case SLJIT_SIG_GREATER_EQUAL:
- GET_CR_BIT(0, reg);
- INVERT_BIT(reg);
- break;
-
- case SLJIT_SIG_GREATER:
- GET_CR_BIT(1, reg);
- break;
-
case SLJIT_SIG_LESS_EQUAL:
- GET_CR_BIT(1, reg);
- INVERT_BIT(reg);
+ cr_bit = 1;
+ invert = 1;
+ break;
+
+ case SLJIT_EQUAL:
+ cr_bit = 2;
+ break;
+
+ case SLJIT_NOT_EQUAL:
+ cr_bit = 2;
+ invert = 1;
break;
case SLJIT_OVERFLOW:
case SLJIT_MUL_OVERFLOW:
- GET_CR_BIT(3, reg);
+ cr_bit = 3;
break;
case SLJIT_NOT_OVERFLOW:
case SLJIT_MUL_NOT_OVERFLOW:
- GET_CR_BIT(3, reg);
- INVERT_BIT(reg);
+ cr_bit = 3;
+ invert = 1;
+ break;
+
+ case SLJIT_LESS_F64:
+ cr_bit = 4 + 0;
+ break;
+
+ case SLJIT_GREATER_EQUAL_F64:
+ cr_bit = 4 + 0;
+ invert = 1;
+ break;
+
+ case SLJIT_GREATER_F64:
+ cr_bit = 4 + 1;
+ break;
+
+ case SLJIT_LESS_EQUAL_F64:
+ cr_bit = 4 + 1;
+ invert = 1;
break;
case SLJIT_EQUAL_F64:
- GET_CR_BIT(4 + 2, reg);
+ cr_bit = 4 + 2;
break;
case SLJIT_NOT_EQUAL_F64:
- GET_CR_BIT(4 + 2, reg);
- INVERT_BIT(reg);
+ cr_bit = 4 + 2;
+ invert = 1;
break;
case SLJIT_UNORDERED_F64:
- GET_CR_BIT(4 + 3, reg);
+ cr_bit = 4 + 3;
break;
case SLJIT_ORDERED_F64:
- GET_CR_BIT(4 + 3, reg);
- INVERT_BIT(reg);
+ cr_bit = 4 + 3;
+ invert = 1;
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
break;
}
+ FAIL_IF(push_inst(compiler, MFCR | D(reg)));
+ FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + (cr_bit)) << 11) | (31 << 6) | (31 << 1)));
+
+ if (invert)
+ FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
+
if (op < SLJIT_ADD) {
-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if (op == SLJIT_MOV)
- input_flags = WORD_DATA;
- else {
- op = SLJIT_MOV_U32;
- input_flags = INT_DATA;
- }
-#else
- op = SLJIT_MOV;
- input_flags = WORD_DATA;
-#endif
- if (reg != TMP_REG2)
+ if (!(dst & SLJIT_MEM))
return SLJIT_SUCCESS;
- return emit_op(compiler, op, input_flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
+ return emit_op_mem2(compiler, input_flags, reg, dst, dstw, reg, 0);
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
- return sljit_emit_op2(compiler, op | flags, dst, original_dstw, src, srcw, TMP_REG2, 0);
+ if (dst & SLJIT_MEM)
+ return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
+ return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+ return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
@@ -2364,7 +2404,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
sljit_s32 reg;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(1);
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
@@ -2372,7 +2411,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+ reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
diff --git a/pcre/sljit/sljitNativeSPARC_32.c b/pcre/sljit/sljitNativeSPARC_32.c
index 7e589a17c25..ee42130e87e 100644
--- a/pcre/sljit/sljitNativeSPARC_32.c
+++ b/pcre/sljit/sljitNativeSPARC_32.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -60,7 +60,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst));
}
else if (dst != src2)
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
case SLJIT_MOV_U16:
@@ -71,7 +71,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return push_inst(compiler, (op == SLJIT_MOV_S16 ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));
}
else if (dst != src2)
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
case SLJIT_NOT:
@@ -80,18 +80,17 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
- /* sparc 32 does not support SLJIT_KEEP_FLAGS. Not sure I can fix this. */
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS));
FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1)));
FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS));
- FAIL_IF(push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS | (flags & SET_FLAGS)));
+ FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst)));
/* Loop. */
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS));
FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1)));
FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS));
- return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS | (flags & SET_FLAGS));
+ return push_inst(compiler, ADD | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS);
case SLJIT_ADD:
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
@@ -135,7 +134,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
}
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
}
@@ -145,20 +144,22 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_
return push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (init_value & 0x3ff), DR(dst));
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
- sljit_ins *inst = (sljit_ins*)addr;
+ sljit_ins *inst = (sljit_ins *)addr;
- inst[0] = (inst[0] & 0xffc00000) | ((new_addr >> 10) & 0x3fffff);
- inst[1] = (inst[1] & 0xfffffc00) | (new_addr & 0x3ff);
+ inst[0] = (inst[0] & 0xffc00000) | ((new_target >> 10) & 0x3fffff);
+ inst[1] = (inst[1] & 0xfffffc00) | (new_target & 0x3ff);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_ins *inst = (sljit_ins*)addr;
+ sljit_ins *inst = (sljit_ins *)addr;
inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff);
inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
diff --git a/pcre/sljit/sljitNativeSPARC_common.c b/pcre/sljit/sljitNativeSPARC_common.c
index ba77c70d521..9831bd83d72 100644
--- a/pcre/sljit/sljitNativeSPARC_common.c
+++ b/pcre/sljit/sljitNativeSPARC_common.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -199,7 +199,7 @@ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
{
sljit_sw diff;
sljit_uw target_addr;
@@ -213,7 +213,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
target_addr = jump->u.target;
else {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- target_addr = (sljit_uw)(code + jump->u.label->size);
+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
}
inst = (sljit_ins*)jump->addr;
@@ -239,8 +239,9 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
if (jump->flags & IS_COND)
inst--;
+ diff = ((sljit_sw)target_addr - (sljit_sw)(inst - 1) - executable_offset) >> 2;
+
if (jump->flags & IS_MOVABLE) {
- diff = ((sljit_sw)target_addr - (sljit_sw)(inst - 1)) >> 2;
if (diff <= MAX_DISP && diff >= MIN_DISP) {
jump->flags |= PATCH_B;
inst--;
@@ -257,7 +258,8 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
}
}
- diff = ((sljit_sw)target_addr - (sljit_sw)(inst)) >> 2;
+ diff += sizeof(sljit_ins);
+
if (diff <= MAX_DISP && diff >= MIN_DISP) {
jump->flags |= PATCH_B;
if (jump->flags & IS_COND)
@@ -280,6 +282,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_sw executable_offset;
sljit_uw addr;
struct sljit_label *label;
@@ -296,9 +299,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ executable_offset = SLJIT_EXEC_OFFSET(code);
+
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+
do {
buf_ptr = (sljit_ins*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 2);
@@ -310,7 +316,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* These structures are ordered by their address. */
if (label && label->size == word_count) {
/* Just recording the address. */
- label->addr = (sljit_uw)code_ptr;
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = code_ptr - code;
label = label->next;
}
@@ -320,7 +326,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#else
jump->addr = (sljit_uw)(code_ptr - 6);
#endif
- code_ptr = detect_jump_type(jump, code_ptr, code);
+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
jump = jump->next;
}
if (const_ && const_->addr == word_count) {
@@ -336,7 +342,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} while (buf);
if (label && label->size == word_count) {
- label->addr = (sljit_uw)code_ptr;
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = code_ptr - code;
label = label->next;
}
@@ -350,16 +356,16 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
while (jump) {
do {
addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
- buf_ptr = (sljit_ins*)jump->addr;
+ buf_ptr = (sljit_ins *)jump->addr;
if (jump->flags & PATCH_CALL) {
- addr = (sljit_sw)(addr - jump->addr) >> 2;
+ addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
SLJIT_ASSERT((sljit_sw)addr <= 0x1fffffff && (sljit_sw)addr >= -0x20000000);
buf_ptr[0] = CALL | (addr & 0x3fffffff);
break;
}
if (jump->flags & PATCH_B) {
- addr = (sljit_sw)(addr - jump->addr) >> 2;
+ addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
SLJIT_ASSERT((sljit_sw)addr <= MAX_DISP && (sljit_sw)addr >= MIN_DISP);
buf_ptr[0] = (buf_ptr[0] & ~DISP_MASK) | (addr & DISP_MASK);
break;
@@ -378,12 +384,37 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
- SLJIT_ENABLE_EXEC(code, code_ptr);
+
+ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
SLJIT_CACHE_FLUSH(code, code_ptr);
return code;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#else
+ /* Available by default. */
+ return 1;
+#endif
+
+#if (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)
+ case SLJIT_HAS_CMOV:
+ return 1;
+#endif
+
+ default:
+ return 0;
+ }
+}
+
/* --------------------------------------------------------------------- */
/* Entry, exit */
/* --------------------------------------------------------------------- */
@@ -568,7 +599,6 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
base = arg & REG_MASK;
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
argw &= 0x3;
- SLJIT_ASSERT(argw != 0);
/* Using the cache. */
if (((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) && (argw == compiler->cache_argw))
@@ -653,18 +683,16 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
compiler->cache_argw = 0;
}
- if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
- if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM))
- return SLJIT_SUCCESS;
+ if (dst != SLJIT_UNUSED) {
+ if (FAST_IS_REG(dst)) {
+ dst_r = dst;
+ flags |= REG_DEST;
+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
+ sugg_src2_r = dst_r;
+ }
+ else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
+ flags |= SLOW_DEST;
}
- else if (FAST_IS_REG(dst)) {
- dst_r = dst;
- flags |= REG_DEST;
- if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
- sugg_src2_r = dst_r;
- }
- else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
- flags |= SLOW_DEST;
if (flags & IMM_OP) {
if ((src2 & SLJIT_IMM) && src2w) {
@@ -813,13 +841,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
- sljit_s32 flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+ sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
CHECK_ERROR();
CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+ return SLJIT_SUCCESS;
+
op = GET_OPCODE(op);
switch (op) {
case SLJIT_MOV:
@@ -882,7 +913,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- sljit_s32 flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+ sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
CHECK_ERROR();
CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -890,6 +921,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+ return SLJIT_SUCCESS;
+
op = GET_OPCODE(op);
switch (op) {
case SLJIT_ADD:
@@ -911,7 +945,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
if (src2 & SLJIT_IMM)
src2w &= 0x1f;
#else
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
#endif
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
}
@@ -944,16 +978,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
- return SLJIT_IS_FPU_AVAILABLE;
-#else
- /* Available by default. */
- return 1;
-#endif
-}
-
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))
#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
#define FLOAT_TMP_MEM_OFFSET (22 * sizeof(sljit_sw))
@@ -971,9 +995,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOI, FDTOI) | DA(TMP_FREG1) | S2A(src), MOVABLE_INS));
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
if (FAST_IS_REG(dst)) {
FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
return emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET);
@@ -1187,10 +1208,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
- /* For UNUSED dst. Uncommon, but possible. */
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
if (FAST_IS_REG(dst))
return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), DR(dst));
@@ -1286,7 +1303,7 @@ static sljit_ins get_cc(sljit_s32 type)
return DA(0xf);
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return DA(0x8);
}
}
@@ -1296,7 +1313,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
struct sljit_jump *jump;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
CHECK_PTR(check_sljit_emit_jump(compiler, type));
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -1375,30 +1391,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src, sljit_sw srcw,
sljit_s32 type)
{
- sljit_s32 reg, flags = (GET_FLAGS(op) ? SET_FLAGS : 0);
+ sljit_s32 reg, flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
CHECK_ERROR();
- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
op = GET_OPCODE(op);
reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
- ADJUST_LOCAL_OFFSET(src, srcw);
- FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
- src = TMP_REG1;
- srcw = 0;
- }
+
+ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));
type &= 0xff;
if (type < SLJIT_EQUAL_F64)
@@ -1409,10 +1418,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(1), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(0), UNMOVABLE_INS));
- if (op >= SLJIT_ADD)
- return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
+ if (op >= SLJIT_ADD) {
+ flags |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE;
+ if (dst & SLJIT_MEM)
+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
+ return emit_op(compiler, op, flags, dst, 0, dst, 0, TMP_REG2, 0);
+ }
- return (reg == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+
+ return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw);
+#else
+#error "Implementation required"
+#endif
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
#else
#error "Implementation required"
#endif
@@ -1424,7 +1454,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
struct sljit_const *const_;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(1);
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
@@ -1432,7 +1461,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+ reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
diff --git a/pcre/sljit/sljitNativeTILEGX-encoder.c b/pcre/sljit/sljitNativeTILEGX-encoder.c
index 719632908c8..dd82ebae6a9 100644
--- a/pcre/sljit/sljitNativeTILEGX-encoder.c
+++ b/pcre/sljit/sljitNativeTILEGX-encoder.c
@@ -2,7 +2,7 @@
* Stack-less Just-In-Time compiler
*
* Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved.
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
diff --git a/pcre/sljit/sljitNativeTILEGX_64.c b/pcre/sljit/sljitNativeTILEGX_64.c
index d92b8582b7e..003f43a7909 100644
--- a/pcre/sljit/sljitNativeTILEGX_64.c
+++ b/pcre/sljit/sljitNativeTILEGX_64.c
@@ -2,7 +2,7 @@
* Stack-less Just-In-Time compiler
*
* Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved.
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -687,7 +687,7 @@ static sljit_s32 update_buffer(struct sljit_compiler *compiler)
inst_buf[0] = inst1;
inst_buf_index = 1;
} else
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
#ifdef TILEGX_JIT_DEBUG
return push_inst_nodebug(compiler, bits);
@@ -727,10 +727,10 @@ static sljit_s32 update_buffer(struct sljit_compiler *compiler)
return push_inst(compiler, bits);
#endif
} else
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
static sljit_s32 flush_buffer(struct sljit_compiler *compiler)
@@ -814,7 +814,7 @@ static sljit_s32 push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic
break;
default:
printf("unrecoginzed opc: %s\n", opcode->name);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
inst_buf_index++;
@@ -859,7 +859,7 @@ static sljit_s32 push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic
break;
default:
printf("unrecoginzed opc: %s\n", opcode->name);
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
inst_buf_index++;
@@ -1113,7 +1113,6 @@ SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compi
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
- SLJIT_ENABLE_EXEC(code, code_ptr);
SLJIT_CACHE_FLUSH(code, code_ptr);
return code;
}
@@ -1953,7 +1952,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return SLJIT_SUCCESS;
}
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
}
@@ -2093,9 +2092,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
op = GET_OPCODE(op);
if (op == SLJIT_MOV_S32 || op == SLJIT_MOV_U32)
mem_type = INT_DATA | SIGNED_DATA;
@@ -2144,7 +2140,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
break;
default:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
dst_ar = sugg_dst_ar;
break;
}
@@ -2187,7 +2183,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
case SLJIT_DIVMOD_SW:
case SLJIT_DIV_UW:
case SLJIT_DIV_SW:
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
return SLJIT_SUCCESS;
@@ -2413,7 +2409,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil
flush_buffer(compiler);
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
CHECK_PTR(check_sljit_emit_jump(compiler, type));
jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -2489,19 +2484,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil
return jump;
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
-{
- return 0;
-}
-
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw)
{
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)
{
- SLJIT_ASSERT_STOP();
+ SLJIT_UNREACHABLE();
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
@@ -2512,7 +2502,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_comp
flush_buffer(compiler);
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(1);
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
@@ -2529,13 +2518,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_comp
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target)
{
sljit_ins *inst = (sljit_ins *)addr;
- inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_addr >> 32) & 0xffff) << 43);
- inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_addr >> 16) & 0xffff) << 43);
- inst[2] = (inst[2] & ~(0xFFFFL << 43)) | ((new_addr & 0xffff) << 43);
+ inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_target >> 32) & 0xffff) << 43);
+ inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_target >> 16) & 0xffff) << 43);
+ inst[2] = (inst[2] & ~(0xFFFFL << 43)) | ((new_target & 0xffff) << 43);
SLJIT_CACHE_FLUSH(inst, inst + 3);
}
diff --git a/pcre/sljit/sljitNativeX86_32.c b/pcre/sljit/sljitNativeX86_32.c
index 78f3dcb06f9..f5cf8834b08 100644
--- a/pcre/sljit/sljitNativeX86_32.c
+++ b/pcre/sljit/sljitNativeX86_32.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -38,7 +38,7 @@ static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, s
return SLJIT_SUCCESS;
}
-static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type)
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset)
{
if (type == SLJIT_JUMP) {
*code_ptr++ = JMP_i32;
@@ -57,7 +57,7 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
if (jump->flags & JUMP_LABEL)
jump->flags |= PATCH_MW;
else
- sljit_unaligned_store_sw(code_ptr, jump->u.target - (jump->addr + 4));
+ sljit_unaligned_store_sw(code_ptr, jump->u.target - (jump->addr + 4) - (sljit_uw)executable_offset);
code_ptr += 4;
return code_ptr;
@@ -75,9 +75,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
compiler->args = args;
- compiler->flags_saved = 0;
- size = 1 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3);
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ /* [esp+0] for saving temporaries and third argument for calls. */
+ compiler->saveds_offset = 1 * sizeof(sljit_sw);
+#else
+ /* [esp+0] for saving temporaries and space for maximum three arguments. */
+ if (scratches <= 1)
+ compiler->saveds_offset = 1 * sizeof(sljit_sw);
+ else
+ compiler->saveds_offset = ((scratches == 2) ? 2 : 3) * sizeof(sljit_sw);
+#endif
+
+ if (scratches > 3)
+ compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);
+
+ compiler->locals_offset = compiler->saveds_offset;
+
+ if (saveds > 3)
+ compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw);
+
+ if (options & SLJIT_F64_ALIGNMENT)
+ compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1);
+
+ size = 1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3);
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
size += (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
#else
@@ -94,11 +115,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
*inst++ = MOD_REG | (reg_map[TMP_REG1] << 3) | 0x4 /* esp */;
}
#endif
- if (saveds > 2 || scratches > 7)
+ if (saveds > 2 || scratches > 9)
PUSH_REG(reg_map[SLJIT_S2]);
- if (saveds > 1 || scratches > 8)
+ if (saveds > 1 || scratches > 10)
PUSH_REG(reg_map[SLJIT_S1]);
- if (saveds > 0 || scratches > 9)
+ if (saveds > 0 || scratches > 11)
PUSH_REG(reg_map[SLJIT_S0]);
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
@@ -134,51 +155,64 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
}
#endif
- SLJIT_COMPILE_ASSERT(SLJIT_LOCALS_OFFSET >= (2 + 4) * sizeof(sljit_uw), require_at_least_two_words);
+ SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0);
+
#if defined(__APPLE__)
/* Ignore pushed registers and SLJIT_LOCALS_OFFSET when computing the aligned local size. */
- saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
+ saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
#else
- if (options & SLJIT_DOUBLE_ALIGNMENT) {
- local_size = SLJIT_LOCALS_OFFSET + ((local_size + 7) & ~7);
-
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 17);
- FAIL_IF(!inst);
-
- INC_SIZE(17);
- inst[0] = MOV_r_rm;
- inst[1] = MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[SLJIT_SP];
- inst[2] = GROUP_F7;
- inst[3] = MOD_REG | (0 << 3) | reg_map[SLJIT_SP];
- sljit_unaligned_store_sw(inst + 4, 0x4);
- inst[8] = JNE_i8;
- inst[9] = 6;
- inst[10] = GROUP_BINARY_81;
- inst[11] = MOD_REG | (5 << 3) | reg_map[SLJIT_SP];
- sljit_unaligned_store_sw(inst + 12, 0x4);
- inst[16] = PUSH_r + reg_map[TMP_REG1];
- }
+ if (options & SLJIT_F64_ALIGNMENT)
+ local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1));
else
- local_size = SLJIT_LOCALS_OFFSET + ((local_size + 3) & ~3);
+ local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1));
#endif
compiler->local_size = local_size;
+
#ifdef _WIN32
if (local_size > 1024) {
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size));
#else
- local_size -= SLJIT_LOCALS_OFFSET;
+ /* Space for a single argument. This amount is excluded when the stack is allocated below. */
+ local_size -= sizeof(sljit_sw);
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size));
FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
- SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, SLJIT_LOCALS_OFFSET));
+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, sizeof(sljit_sw)));
#endif
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
}
#endif
SLJIT_ASSERT(local_size > 0);
+
+#if !defined(__APPLE__)
+ if (options & SLJIT_F64_ALIGNMENT) {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SP, 0);
+
+ /* Some space might allocated during sljit_grow_stack() above on WIN32. */
+ FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size + sizeof(sljit_sw)));
+
+#if defined _WIN32 && !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (compiler->local_size > 1024)
+ FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+ TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, sizeof(sljit_sw)));
+#endif
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 6);
+ FAIL_IF(!inst);
+
+ INC_SIZE(6);
+ inst[0] = GROUP_BINARY_81;
+ inst[1] = MOD_REG | AND | reg_map[SLJIT_SP];
+ sljit_unaligned_store_sw(inst + 2, ~(sizeof(sljit_f64) - 1));
+
+ /* The real local size must be used. */
+ return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), compiler->local_size, TMP_REG1, 0);
+ }
+#endif
return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size);
}
@@ -193,14 +227,36 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
compiler->args = args;
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ /* [esp+0] for saving temporaries and third argument for calls. */
+ compiler->saveds_offset = 1 * sizeof(sljit_sw);
+#else
+ /* [esp+0] for saving temporaries and space for maximum three arguments. */
+ if (scratches <= 1)
+ compiler->saveds_offset = 1 * sizeof(sljit_sw);
+ else
+ compiler->saveds_offset = ((scratches == 2) ? 2 : 3) * sizeof(sljit_sw);
+#endif
+
+ if (scratches > 3)
+ compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);
+
+ compiler->locals_offset = compiler->saveds_offset;
+
+ if (saveds > 3)
+ compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw);
+
+ if (options & SLJIT_F64_ALIGNMENT)
+ compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1);
+
#if defined(__APPLE__)
- saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
+ saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
compiler->local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
#else
- if (options & SLJIT_DOUBLE_ALIGNMENT)
- compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + 7) & ~7);
+ if (options & SLJIT_F64_ALIGNMENT)
+ compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1));
else
- compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + 3) & ~3);
+ compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1));
#endif
return SLJIT_SUCCESS;
}
@@ -214,23 +270,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
CHECK(check_sljit_emit_return(compiler, op, src, srcw));
SLJIT_ASSERT(compiler->args >= 0);
- compiler->flags_saved = 0;
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
SLJIT_ASSERT(compiler->local_size > 0);
- FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
- SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
#if !defined(__APPLE__)
- if (compiler->options & SLJIT_DOUBLE_ALIGNMENT) {
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);
- FAIL_IF(!inst);
-
- INC_SIZE(3);
- inst[0] = MOV_r_rm;
- inst[1] = (reg_map[SLJIT_SP] << 3) | 0x4 /* SIB */;
- inst[2] = (4 << 3) | reg_map[SLJIT_SP];
- }
+ if (compiler->options & SLJIT_F64_ALIGNMENT)
+ EMIT_MOV(compiler, SLJIT_SP, 0, SLJIT_MEM1(SLJIT_SP), compiler->local_size)
+ else
+ FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
+#else
+ FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
#endif
size = 2 + (compiler->scratches > 7 ? (compiler->scratches - 7) : 0) +
@@ -247,11 +299,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
INC_SIZE(size);
- if (compiler->saveds > 0 || compiler->scratches > 9)
+ if (compiler->saveds > 0 || compiler->scratches > 11)
POP_REG(reg_map[SLJIT_S0]);
- if (compiler->saveds > 1 || compiler->scratches > 8)
+ if (compiler->saveds > 1 || compiler->scratches > 10)
POP_REG(reg_map[SLJIT_S1]);
- if (compiler->saveds > 2 || compiler->scratches > 7)
+ if (compiler->saveds > 2 || compiler->scratches > 9)
POP_REG(reg_map[SLJIT_S2]);
POP_REG(reg_map[TMP_REG1]);
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
diff --git a/pcre/sljit/sljitNativeX86_64.c b/pcre/sljit/sljitNativeX86_64.c
index e88ddedcd1c..039b68c45ab 100644
--- a/pcre/sljit/sljitNativeX86_64.c
+++ b/pcre/sljit/sljitNativeX86_64.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -47,9 +47,8 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
*code_ptr++ = 10 + 3;
}
- SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first);
- *code_ptr++ = REX_W | REX_B;
- *code_ptr++ = MOV_r_i32 + 1;
+ *code_ptr++ = REX_W | ((reg_map[TMP_REG2] <= 7) ? 0 : REX_B);
+ *code_ptr++ = MOV_r_i32 | reg_lmap[TMP_REG2];
jump->addr = (sljit_uw)code_ptr;
if (jump->flags & JUMP_LABEL)
@@ -58,31 +57,10 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
sljit_unaligned_store_sw(code_ptr, jump->u.target);
code_ptr += sizeof(sljit_sw);
- *code_ptr++ = REX_B;
- *code_ptr++ = GROUP_FF;
- *code_ptr++ = (type >= SLJIT_FAST_CALL) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
-
- return code_ptr;
-}
-
-static sljit_u8* generate_fixed_jump(sljit_u8 *code_ptr, sljit_sw addr, sljit_s32 type)
-{
- sljit_sw delta = addr - ((sljit_sw)code_ptr + 1 + sizeof(sljit_s32));
-
- if (delta <= HALFWORD_MAX && delta >= HALFWORD_MIN) {
- *code_ptr++ = (type == 2) ? CALL_i32 : JMP_i32;
- sljit_unaligned_store_sw(code_ptr, delta);
- }
- else {
- SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second);
- *code_ptr++ = REX_W | REX_B;
- *code_ptr++ = MOV_r_i32 + 1;
- sljit_unaligned_store_sw(code_ptr, addr);
- code_ptr += sizeof(sljit_sw);
+ if (reg_map[TMP_REG2] >= 8)
*code_ptr++ = REX_B;
- *code_ptr++ = GROUP_FF;
- *code_ptr++ = (type == 2) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
- }
+ *code_ptr++ = GROUP_FF;
+ *code_ptr++ = MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2];
return code_ptr;
}
@@ -98,7 +76,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
- compiler->flags_saved = 0;
+#ifdef _WIN64
+ /* Two/four register slots for parameters plus space for xmm6 register if needed. */
+ if (fscratches >= 6 || fsaveds >= 1)
+ compiler->locals_offset = 6 * sizeof(sljit_sw);
+ else
+ compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw);
+#endif
/* Including the return address saved by the call instruction. */
saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
@@ -177,7 +161,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
INC_SIZE(4 + (3 + sizeof(sljit_s32)));
*inst++ = REX_W;
*inst++ = GROUP_BINARY_83;
- *inst++ = MOD_REG | SUB | 4;
+ *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
/* Allocated size for registers must be divisible by 8. */
SLJIT_ASSERT(!(saved_register_size & 0x7));
/* Aligned to 16 byte. */
@@ -189,7 +173,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
local_size -= 4 * sizeof(sljit_sw);
}
/* Second instruction */
- SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R0] < 8, temporary_reg1_is_loreg);
+ SLJIT_ASSERT(reg_map[SLJIT_R0] < 8);
*inst++ = REX_W;
*inst++ = MOV_rm_i32;
*inst++ = MOD_REG | reg_lmap[SLJIT_R0];
@@ -202,25 +186,26 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
}
#endif
- SLJIT_ASSERT(local_size > 0);
- if (local_size <= 127) {
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
- FAIL_IF(!inst);
- INC_SIZE(4);
- *inst++ = REX_W;
- *inst++ = GROUP_BINARY_83;
- *inst++ = MOD_REG | SUB | 4;
- *inst++ = local_size;
- }
- else {
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 7);
- FAIL_IF(!inst);
- INC_SIZE(7);
- *inst++ = REX_W;
- *inst++ = GROUP_BINARY_81;
- *inst++ = MOD_REG | SUB | 4;
- sljit_unaligned_store_s32(inst, local_size);
- inst += sizeof(sljit_s32);
+ if (local_size > 0) {
+ if (local_size <= 127) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ *inst++ = REX_W;
+ *inst++ = GROUP_BINARY_83;
+ *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
+ *inst++ = local_size;
+ }
+ else {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 7);
+ FAIL_IF(!inst);
+ INC_SIZE(7);
+ *inst++ = REX_W;
+ *inst++ = GROUP_BINARY_81;
+ *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
+ sljit_unaligned_store_s32(inst, local_size);
+ inst += sizeof(sljit_s32);
+ }
}
#ifdef _WIN64
@@ -247,6 +232,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
+#ifdef _WIN64
+ /* Two/four register slots for parameters plus space for xmm6 register if needed. */
+ if (fscratches >= 6 || fsaveds >= 1)
+ compiler->locals_offset = 6 * sizeof(sljit_sw);
+ else
+ compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw);
+#endif
+
/* Including the return address saved by the call instruction. */
saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
compiler->local_size = ((local_size + SLJIT_LOCALS_OFFSET + saved_register_size + 15) & ~15) - saved_register_size;
@@ -261,7 +254,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
CHECK_ERROR();
CHECK(check_sljit_emit_return(compiler, op, src, srcw));
- compiler->flags_saved = 0;
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
#ifdef _WIN64
@@ -275,24 +267,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
}
#endif
- SLJIT_ASSERT(compiler->local_size > 0);
- if (compiler->local_size <= 127) {
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
- FAIL_IF(!inst);
- INC_SIZE(4);
- *inst++ = REX_W;
- *inst++ = GROUP_BINARY_83;
- *inst++ = MOD_REG | ADD | 4;
- *inst = compiler->local_size;
- }
- else {
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 7);
- FAIL_IF(!inst);
- INC_SIZE(7);
- *inst++ = REX_W;
- *inst++ = GROUP_BINARY_81;
- *inst++ = MOD_REG | ADD | 4;
- sljit_unaligned_store_s32(inst, compiler->local_size);
+ if (compiler->local_size > 0) {
+ if (compiler->local_size <= 127) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ *inst++ = REX_W;
+ *inst++ = GROUP_BINARY_83;
+ *inst++ = MOD_REG | ADD | 4;
+ *inst = compiler->local_size;
+ }
+ else {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 7);
+ FAIL_IF(!inst);
+ INC_SIZE(7);
+ *inst++ = REX_W;
+ *inst++ = GROUP_BINARY_81;
+ *inst++ = MOD_REG | ADD | 4;
+ sljit_unaligned_store_s32(inst, compiler->local_size);
+ }
}
tmp = compiler->scratches;
@@ -387,13 +380,12 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
if (b & SLJIT_MEM) {
if (!(b & OFFS_REG_MASK)) {
if (NOT_HALFWORD(immb)) {
- if (emit_load_imm64(compiler, TMP_REG3, immb))
- return NULL;
+ PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
immb = 0;
if (b & REG_MASK)
- b |= TO_OFFS_REG(TMP_REG3);
+ b |= TO_OFFS_REG(TMP_REG2);
else
- b |= TMP_REG3;
+ b |= TMP_REG2;
}
else if (reg_lmap[b & REG_MASK] == 4)
b |= TO_OFFS_REG(SLJIT_SP);
@@ -553,17 +545,19 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
/* Call / return instructions */
/* --------------------------------------------------------------------- */
-static SLJIT_INLINE sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 type)
+static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 type)
{
sljit_u8 *inst;
+ /* After any change update IS_REG_CHANGED_BY_CALL as well. */
#ifndef _WIN64
- SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers);
+ SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8 && reg_map[TMP_REG1] == 2);
inst = (sljit_u8*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
FAIL_IF(!inst);
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
if (type >= SLJIT_CALL3) {
+ /* Move third argument to TMP_REG1. */
*inst++ = REX_W;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_R2];
@@ -572,12 +566,13 @@ static SLJIT_INLINE sljit_s32 call_with_args(struct sljit_compiler *compiler, sl
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_R0];
#else
- SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers);
+ SLJIT_ASSERT(reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8 && reg_map[TMP_REG1] == 8);
inst = (sljit_u8*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
FAIL_IF(!inst);
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
if (type >= SLJIT_CALL3) {
+ /* Move third argument to TMP_REG1. */
*inst++ = REX_W | REX_R;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_R2];
diff --git a/pcre/sljit/sljitNativeX86_common.c b/pcre/sljit/sljitNativeX86_common.c
index 960bdc2d039..eb0886d6715 100644
--- a/pcre/sljit/sljitNativeX86_common.c
+++ b/pcre/sljit/sljitNativeX86_common.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -67,12 +67,15 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {
- 0, 0, 2, 1, 0, 0, 0, 0, 7, 6, 3, 4, 5
+ 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 7, 6, 3, 4, 5
};
#define CHECK_EXTRA_REGS(p, w, do) \
- if (p >= SLJIT_R3 && p <= SLJIT_R6) { \
- w = SLJIT_LOCALS_OFFSET + ((p) - (SLJIT_R3 + 4)) * sizeof(sljit_sw); \
+ if (p >= SLJIT_R3 && p <= SLJIT_S3) { \
+ if (p <= compiler->scratches) \
+ w = compiler->saveds_offset - ((p) - SLJIT_R2) * (sljit_sw)sizeof(sljit_sw); \
+ else \
+ w = compiler->locals_offset + ((p) - SLJIT_S2) * (sljit_sw)sizeof(sljit_sw); \
p = SLJIT_MEM1(SLJIT_SP); \
do; \
}
@@ -82,28 +85,27 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {
/* Last register + 1. */
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
-#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
/* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present
Note: avoid to use r12 and r13 for memory addessing
- therefore r12 is better for SAVED_EREG than SAVED_REG. */
+ therefore r12 is better to be a higher saved register. */
#ifndef _WIN64
-/* 1st passed in rdi, 2nd argument passed in rsi, 3rd in rdx. */
-static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
- 0, 0, 6, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 7, 9
+/* Args: rdi(=7), rsi(=6), rdx(=2), rcx(=1), r8, r9. Scratches: rax(=0), r10, r11 */
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+ 0, 0, 6, 1, 7, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 9
};
/* low-map. reg_map & 0x7. */
-static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = {
- 0, 0, 6, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 7, 1
+static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+ 0, 0, 6, 1, 7, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1
};
#else
-/* 1st passed in rcx, 2nd argument passed in rdx, 3rd in r8. */
-static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
- 0, 0, 2, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 10, 8, 9
+/* Args: rcx(=1), rdx(=2), r8, r9. Scratches: rax(=0), r10, r11 */
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+ 0, 0, 2, 1, 10, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 8, 9
};
/* low-map. reg_map & 0x7. */
-static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = {
- 0, 0, 2, 1, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 2, 0, 1
+static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+ 0, 0, 2, 1, 2, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 0, 1
};
#endif
@@ -166,7 +168,7 @@ static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = {
#define CALL_i32 0xe8
#define CALL_rm (/* GROUP_FF */ 2 << 3)
#define CDQ 0x99
-#define CMOVNE_r_rm (/* GROUP_0F */ 0x45)
+#define CMOVE_r_rm (/* GROUP_0F */ 0x44)
#define CMP (/* BINARY */ 7 << 3)
#define CMP_EAX_i32 0x3d
#define CMP_r_rm 0x3b
@@ -214,6 +216,7 @@ static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = {
#define POP_r 0x58
#define POP_rm 0x8f
#define POPF 0x9d
+#define PREFETCH 0x18
#define PUSH_i32 0x68
#define PUSH_r 0x50
#define PUSH_rm (/* GROUP_FF */ 6 << 3)
@@ -409,13 +412,13 @@ static sljit_u8 get_jump_code(sljit_s32 type)
return 0;
}
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset);
+#else
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type);
-
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-static sljit_u8* generate_fixed_jump(sljit_u8 *code_ptr, sljit_sw addr, sljit_s32 type);
#endif
-static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_s32 type)
+static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_s32 type, sljit_sw executable_offset)
{
sljit_s32 short_jump;
sljit_uw label_addr;
@@ -423,7 +426,8 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code
if (jump->flags & JUMP_LABEL)
label_addr = (sljit_uw)(code + jump->u.label->size);
else
- label_addr = jump->u.target;
+ label_addr = jump->u.target - executable_offset;
+
short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@@ -476,6 +480,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_u8 *buf_ptr;
sljit_u8 *buf_end;
sljit_u8 len;
+ sljit_sw executable_offset;
+ sljit_sw jump_addr;
struct sljit_label *label;
struct sljit_jump *jump;
@@ -494,6 +500,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ executable_offset = SLJIT_EXEC_OFFSET(code);
+
do {
buf_ptr = buf->memory;
buf_end = buf_ptr + buf->used_size;
@@ -506,35 +514,28 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr += len;
}
else {
- if (*buf_ptr >= 4) {
+ if (*buf_ptr >= 2) {
jump->addr = (sljit_uw)code_ptr;
if (!(jump->flags & SLJIT_REWRITABLE_JUMP))
- code_ptr = generate_near_jump_code(jump, code_ptr, code, *buf_ptr - 4);
- else
- code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 4);
+ code_ptr = generate_near_jump_code(jump, code_ptr, code, *buf_ptr - 2, executable_offset);
+ else {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2, executable_offset);
+#else
+ code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2);
+#endif
+ }
jump = jump->next;
}
else if (*buf_ptr == 0) {
- label->addr = (sljit_uw)code_ptr;
+ label->addr = ((sljit_uw)code_ptr) + executable_offset;
label->size = code_ptr - code;
label = label->next;
}
- else if (*buf_ptr == 1) {
+ else { /* *buf_ptr is 1 */
const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw);
const_ = const_->next;
}
- else {
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- *code_ptr++ = (*buf_ptr == 2) ? CALL_i32 : JMP_i32;
- buf_ptr++;
- sljit_unaligned_store_sw(code_ptr, *(sljit_sw*)buf_ptr - ((sljit_sw)code_ptr + sizeof(sljit_sw)));
- code_ptr += sizeof(sljit_sw);
- buf_ptr += sizeof(sljit_sw) - 1;
-#else
- code_ptr = generate_fixed_jump(code_ptr, *(sljit_sw*)(buf_ptr + 1), *buf_ptr);
- buf_ptr += sizeof(sljit_sw);
-#endif
- }
buf_ptr++;
}
} while (buf_ptr < buf_end);
@@ -548,24 +549,26 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = compiler->jumps;
while (jump) {
+ jump_addr = jump->addr + executable_offset;
+
if (jump->flags & PATCH_MB) {
- SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_s8))) >= -128 && (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_s8))) <= 127);
- *(sljit_u8*)jump->addr = (sljit_u8)(jump->u.label->addr - (jump->addr + sizeof(sljit_s8)));
+ SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) >= -128 && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) <= 127);
+ *(sljit_u8*)jump->addr = (sljit_u8)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8)));
} else if (jump->flags & PATCH_MW) {
if (jump->flags & JUMP_LABEL) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sw))));
+ sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_sw))));
#else
- SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_s32))) <= HALFWORD_MAX);
- sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.label->addr - (jump->addr + sizeof(sljit_s32))));
+ SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX);
+ sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))));
#endif
}
else {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_sw))));
+ sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_sw))));
#else
- SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_s32))) <= HALFWORD_MAX);
- sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.target - (jump->addr + sizeof(sljit_s32))));
+ SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX);
+ sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.target - (jump_addr + sizeof(sljit_s32))));
#endif
}
}
@@ -577,12 +580,54 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
- /* Maybe we waste some space because of short jumps. */
+ /* Some space may be wasted because of short jumps. */
SLJIT_ASSERT(code_ptr <= code + compiler->size);
compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
compiler->executable_size = code_ptr - code;
- SLJIT_ENABLE_EXEC(code, code_ptr);
- return (void*)code;
+ return (void*)(code + executable_offset);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return SLJIT_IS_FPU_AVAILABLE;
+#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
+ if (cpu_has_sse2 == -1)
+ get_cpu_features();
+ return cpu_has_sse2;
+#else /* SLJIT_DETECT_SSE2 */
+ return 1;
+#endif /* SLJIT_DETECT_SSE2 */
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ case SLJIT_HAS_VIRTUAL_REGISTERS:
+ return 1;
+#endif
+
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_CMOV:
+ if (cpu_has_cmov == -1)
+ get_cpu_features();
+ return cpu_has_cmov;
+
+ case SLJIT_HAS_PREF_SHIFT_REG:
+ return 1;
+
+ case SLJIT_HAS_SSE2:
+#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
+ if (cpu_has_sse2 == -1)
+ get_cpu_features();
+ return cpu_has_sse2;
+#else
+ return 1;
+#endif
+
+ default:
+ return 0;
+ }
}
/* --------------------------------------------------------------------- */
@@ -605,52 +650,8 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw);
-static SLJIT_INLINE sljit_s32 emit_save_flags(struct sljit_compiler *compiler)
-{
- sljit_u8 *inst;
-
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);
- FAIL_IF(!inst);
- INC_SIZE(5);
-#else
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 6);
- FAIL_IF(!inst);
- INC_SIZE(6);
- *inst++ = REX_W;
-#endif
- *inst++ = LEA_r_m; /* lea esp/rsp, [esp/rsp + sizeof(sljit_sw)] */
- *inst++ = 0x64;
- *inst++ = 0x24;
- *inst++ = (sljit_u8)sizeof(sljit_sw);
- *inst++ = PUSHF;
- compiler->flags_saved = 1;
- return SLJIT_SUCCESS;
-}
-
-static SLJIT_INLINE sljit_s32 emit_restore_flags(struct sljit_compiler *compiler, sljit_s32 keep_flags)
-{
- sljit_u8 *inst;
-
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);
- FAIL_IF(!inst);
- INC_SIZE(5);
- *inst++ = POPF;
-#else
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 6);
- FAIL_IF(!inst);
- INC_SIZE(6);
- *inst++ = POPF;
- *inst++ = REX_W;
-#endif
- *inst++ = LEA_r_m; /* lea esp/rsp, [esp/rsp - sizeof(sljit_sw)] */
- *inst++ = 0x64;
- *inst++ = 0x24;
- *inst++ = (sljit_u8)(-(sljit_s8)sizeof(sljit_sw));
- compiler->flags_saved = keep_flags;
- return SLJIT_SUCCESS;
-}
+#define EMIT_MOV(compiler, dst, dstw, src, srcw) \
+ FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
#ifdef _WIN32
#include
@@ -681,15 +682,8 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler,
{
sljit_u8* inst;
- if (dst == SLJIT_UNUSED) {
- /* No destination, doesn't need to setup flags. */
- if (src & SLJIT_MEM) {
- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src, srcw);
- FAIL_IF(!inst);
- *inst = MOV_r_rm;
- }
- return SLJIT_SUCCESS;
- }
+ SLJIT_ASSERT(dst != SLJIT_UNUSED);
+
if (FAST_IS_REG(src)) {
inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);
FAIL_IF(!inst);
@@ -711,8 +705,10 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler,
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (!compiler->mode32 && NOT_HALFWORD(srcw)) {
- FAIL_IF(emit_load_imm64(compiler, TMP_REG2, srcw));
- inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, dst, dstw);
+ /* Immediate to memory move. Only SLJIT_MOV operation copies
+ an immediate directly into memory so TMP_REG1 can be used. */
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw));
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);
FAIL_IF(!inst);
*inst = MOV_rm_r;
return SLJIT_SUCCESS;
@@ -730,7 +726,8 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
- /* Memory to memory move. Requires two instruction. */
+ /* Memory to memory move. Only SLJIT_MOV operation copies
+ data from memory to memory so TMP_REG1 can be used. */
inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src, srcw);
FAIL_IF(!inst);
*inst = MOV_r_rm;
@@ -740,9 +737,6 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
-#define EMIT_MOV(compiler, dst, dstw, src, srcw) \
- FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
-
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
sljit_u8 *inst;
@@ -772,20 +766,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
case SLJIT_DIVMOD_SW:
case SLJIT_DIV_UW:
case SLJIT_DIV_SW:
- compiler->flags_saved = 0;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
#ifdef _WIN64
- SLJIT_COMPILE_ASSERT(
+ SLJIT_ASSERT(
reg_map[SLJIT_R0] == 0
&& reg_map[SLJIT_R1] == 2
- && reg_map[TMP_REG1] > 7,
- invalid_register_assignment_for_div_mul);
+ && reg_map[TMP_REG1] > 7);
#else
- SLJIT_COMPILE_ASSERT(
+ SLJIT_ASSERT(
reg_map[SLJIT_R0] == 0
&& reg_map[SLJIT_R1] < 7
- && reg_map[TMP_REG1] == 2,
- invalid_register_assignment_for_div_mul);
+ && reg_map[TMP_REG1] == 2);
#endif
compiler->mode32 = op & SLJIT_I32_OP;
#endif
@@ -909,9 +900,6 @@ static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign,
compiler->mode32 = 0;
#endif
- if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
- return SLJIT_SUCCESS; /* Empty instruction. */
-
if (src & SLJIT_IMM) {
if (FAST_IS_REG(dst)) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
@@ -1040,6 +1028,30 @@ static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign,
return SLJIT_SUCCESS;
}
+static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8* inst;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif
+
+ inst = emit_x86_instruction(compiler, 2, 0, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst++ = PREFETCH;
+
+ if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8)
+ *inst |= (3 << 3);
+ else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16)
+ *inst |= (2 << 3);
+ else
+ *inst |= (1 << 3);
+
+ return SLJIT_SUCCESS;
+}
+
static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
@@ -1051,9 +1063,6 @@ static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign,
compiler->mode32 = 0;
#endif
- if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
- return SLJIT_SUCCESS; /* Empty instruction. */
-
if (src & SLJIT_IMM) {
if (FAST_IS_REG(dst)) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
@@ -1097,14 +1106,6 @@ static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode,
{
sljit_u8* inst;
- if (dst == SLJIT_UNUSED) {
- EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
- inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
- FAIL_IF(!inst);
- *inst++ = GROUP_F7;
- *inst |= opcode;
- return SLJIT_SUCCESS;
- }
if (dst == src && dstw == srcw) {
/* Same input and output */
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
@@ -1113,14 +1114,19 @@ static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode,
*inst |= opcode;
return SLJIT_SUCCESS;
}
+
+ if (dst == SLJIT_UNUSED)
+ dst = TMP_REG1;
+
if (FAST_IS_REG(dst)) {
EMIT_MOV(compiler, dst, 0, src, srcw);
- inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0);
FAIL_IF(!inst);
*inst++ = GROUP_F7;
*inst |= opcode;
return SLJIT_SUCCESS;
}
+
EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
FAIL_IF(!inst);
@@ -1136,20 +1142,12 @@ static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler,
{
sljit_u8* inst;
- if (dst == SLJIT_UNUSED) {
- EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
- inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
- FAIL_IF(!inst);
- *inst++ = GROUP_F7;
- *inst |= NOT_rm;
- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0);
- FAIL_IF(!inst);
- *inst = OR_r_rm;
- return SLJIT_SUCCESS;
- }
+ if (dst == SLJIT_UNUSED)
+ dst = TMP_REG1;
+
if (FAST_IS_REG(dst)) {
EMIT_MOV(compiler, dst, 0, src, srcw);
- inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0);
FAIL_IF(!inst);
*inst++ = GROUP_F7;
*inst |= NOT_rm;
@@ -1158,6 +1156,7 @@ static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler,
*inst = OR_r_rm;
return SLJIT_SUCCESS;
}
+
EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
FAIL_IF(!inst);
@@ -1170,6 +1169,10 @@ static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+static const sljit_sw emit_clz_arg = 32 + 31;
+#endif
+
static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
@@ -1178,22 +1181,6 @@ static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags,
sljit_s32 dst_r;
SLJIT_UNUSED_ARG(op_flags);
- if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
- /* Just set the zero flag. */
- EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
- inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
- FAIL_IF(!inst);
- *inst++ = GROUP_F7;
- *inst |= NOT_rm;
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 31, TMP_REG1, 0);
-#else
- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? 63 : 31, TMP_REG1, 0);
-#endif
- FAIL_IF(!inst);
- *inst |= SHR;
- return SLJIT_SUCCESS;
- }
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
@@ -1201,81 +1188,53 @@ static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags,
srcw = 0;
}
- inst = emit_x86_instruction(compiler, 2, TMP_REG1, 0, src, srcw);
+ if (cpu_has_cmov == -1)
+ get_cpu_features();
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = GROUP_0F;
*inst = BSR_r_rm;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- if (FAST_IS_REG(dst))
- dst_r = dst;
- else {
- /* Find an unused temporary register. */
- if ((dst & REG_MASK) != SLJIT_R0 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R0))
- dst_r = SLJIT_R0;
- else if ((dst & REG_MASK) != SLJIT_R1 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R1))
- dst_r = SLJIT_R1;
- else
- dst_r = SLJIT_R2;
- EMIT_MOV(compiler, dst, dstw, dst_r, 0);
- }
- EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, 32 + 31);
-#else
- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
- compiler->mode32 = 0;
- EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? 64 + 63 : 32 + 31);
- compiler->mode32 = op_flags & SLJIT_I32_OP;
-#endif
-
- if (cpu_has_cmov == -1)
- get_cpu_features();
-
if (cpu_has_cmov) {
- inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0);
+ if (dst_r != TMP_REG1) {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 32 + 31);
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0);
+ }
+ else
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), (sljit_sw)&emit_clz_arg);
+
FAIL_IF(!inst);
*inst++ = GROUP_0F;
- *inst = CMOVNE_r_rm;
- } else {
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
- FAIL_IF(!inst);
- INC_SIZE(4);
-
- *inst++ = JE_i8;
- *inst++ = 2;
- *inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_map[dst_r] << 3) | reg_map[TMP_REG1];
-#else
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);
- FAIL_IF(!inst);
- INC_SIZE(5);
-
- *inst++ = JE_i8;
- *inst++ = 3;
- *inst++ = REX_W | (reg_map[dst_r] >= 8 ? REX_R : 0) | (reg_map[TMP_REG1] >= 8 ? REX_B : 0);
- *inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_lmap[dst_r] << 3) | reg_lmap[TMP_REG1];
-#endif
+ *inst = CMOVE_r_rm;
}
+ else
+ FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, 32 + 31));
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);
#else
+ if (cpu_has_cmov) {
+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31));
+
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = CMOVE_r_rm;
+ }
+ else
+ FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31)));
+
inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? 63 : 31, dst_r, 0);
#endif
+
FAIL_IF(!inst);
*(inst + 1) |= XOR;
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- if (dst & SLJIT_MEM) {
- inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
- FAIL_IF(!inst);
- *inst = XCHG_r_rm;
- }
-#else
if (dst & SLJIT_MEM)
- EMIT_MOV(compiler, dst, dstw, TMP_REG2, 0);
-#endif
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
return SLJIT_SUCCESS;
}
@@ -1283,7 +1242,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
- sljit_u8* inst;
sljit_s32 update = 0;
sljit_s32 op_flags = GET_ALL_FLAGS(op);
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
@@ -1304,7 +1262,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
compiler->mode32 = op_flags & SLJIT_I32_OP;
#endif
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+ if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
+ return emit_prefetch(compiler, op, src, srcw);
+ return SLJIT_SUCCESS;
+ }
+
op = GET_OPCODE(op);
+
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
compiler->mode32 = 0;
@@ -1362,14 +1327,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
#endif
}
- if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & REG_MASK) && (srcw != 0 || (src & OFFS_REG_MASK) != 0)) {
- inst = emit_x86_instruction(compiler, 1, src & REG_MASK, 0, src, srcw);
- FAIL_IF(!inst);
- *inst = LEA_r_m;
- src &= SLJIT_MEM | 0xf;
- srcw = 0;
- }
-
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P) || (src & SLJIT_MEM))) {
SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_SP));
@@ -1413,31 +1370,40 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0);
#endif
- if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & REG_MASK) && (dstw != 0 || (dst & OFFS_REG_MASK) != 0)) {
- inst = emit_x86_instruction(compiler, 1, dst & REG_MASK, 0, dst, dstw);
- FAIL_IF(!inst);
- *inst = LEA_r_m;
+ if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & REG_MASK)) {
+ if ((src & OFFS_REG_MASK) != 0) {
+ FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+ (src & REG_MASK), 0, (src & REG_MASK), 0, OFFS_REG(dst), 0));
+ }
+ else if (srcw != 0) {
+ FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+ (src & REG_MASK), 0, (src & REG_MASK), 0, SLJIT_IMM, srcw));
+ }
+ }
+
+ if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & REG_MASK)) {
+ if ((dst & OFFS_REG_MASK) != 0) {
+ FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+ (dst & REG_MASK), 0, (dst & REG_MASK), 0, OFFS_REG(dst), 0));
+ }
+ else if (dstw != 0) {
+ FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+ (dst & REG_MASK), 0, (dst & REG_MASK), 0, SLJIT_IMM, dstw));
+ }
}
return SLJIT_SUCCESS;
}
- if (SLJIT_UNLIKELY(GET_FLAGS(op_flags)))
- compiler->flags_saved = 0;
-
switch (op) {
case SLJIT_NOT:
- if (SLJIT_UNLIKELY(op_flags & SLJIT_SET_E))
+ if (SLJIT_UNLIKELY(op_flags & SLJIT_SET_Z))
return emit_not_with_flags(compiler, dst, dstw, src, srcw);
return emit_unary(compiler, NOT_rm, dst, dstw, src, srcw);
case SLJIT_NEG:
- if (SLJIT_UNLIKELY(op_flags & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
- FAIL_IF(emit_save_flags(compiler));
return emit_unary(compiler, NEG_rm, dst, dstw, src, srcw);
case SLJIT_CLZ:
- if (SLJIT_UNLIKELY(op_flags & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
- FAIL_IF(emit_save_flags(compiler));
return emit_clz(compiler, op_flags, dst, dstw, src, srcw);
}
@@ -1457,8 +1423,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
*(inst + 1) |= (op_imm); \
} \
else { \
- FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immw)); \
- inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, arg, argw); \
+ FAIL_IF(emit_load_imm64(compiler, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, immw)); \
+ inst = emit_x86_instruction(compiler, 1, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, 0, arg, argw); \
FAIL_IF(!inst); \
*inst = (op_mr); \
}
@@ -1684,7 +1650,7 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler,
sljit_u8* inst;
sljit_s32 dst_r;
- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
/* Register destination. */
if (dst_r == src1 && !(src2 & SLJIT_IMM)) {
@@ -1736,9 +1702,9 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler,
sljit_unaligned_store_s32(inst, (sljit_s32)src1w);
}
else {
- EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w);
if (dst_r != src2)
EMIT_MOV(compiler, dst_r, 0, src2, src2w);
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));
inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
FAIL_IF(!inst);
*inst++ = GROUP_0F;
@@ -1779,9 +1745,9 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler,
sljit_unaligned_store_s32(inst, (sljit_s32)src2w);
}
else {
- EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src2w);
if (dst_r != src1)
EMIT_MOV(compiler, dst_r, 0, src1, src1w);
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
FAIL_IF(!inst);
*inst++ = GROUP_0F;
@@ -1800,13 +1766,13 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler,
*inst = IMUL_r_rm;
}
- if (dst_r == TMP_REG1)
+ if (dst & SLJIT_MEM)
EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
return SLJIT_SUCCESS;
}
-static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler, sljit_s32 keep_flags,
+static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
@@ -1815,12 +1781,10 @@ static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler, sljit_s32 keep
sljit_s32 dst_r, done = 0;
/* These cases better be left to handled by normal way. */
- if (!keep_flags) {
- if (dst == src1 && dstw == src1w)
- return SLJIT_ERR_UNSUPPORTED;
- if (dst == src2 && dstw == src2w)
- return SLJIT_ERR_UNSUPPORTED;
- }
+ if (dst == src1 && dstw == src1w)
+ return SLJIT_ERR_UNSUPPORTED;
+ if (dst == src2 && dstw == src2w)
+ return SLJIT_ERR_UNSUPPORTED;
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
@@ -1932,7 +1896,7 @@ static sljit_s32 emit_test_binary(struct sljit_compiler *compiler,
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if (src2 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
+ if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
#else
if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) {
#endif
@@ -1949,8 +1913,8 @@ static sljit_s32 emit_test_binary(struct sljit_compiler *compiler,
*inst = GROUP_F7;
}
else {
- FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
- inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, src1w);
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, src2w));
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src1, src1w);
FAIL_IF(!inst);
*inst = TEST_rm_r;
}
@@ -1978,8 +1942,8 @@ static sljit_s32 emit_test_binary(struct sljit_compiler *compiler,
*inst = GROUP_F7;
}
else {
- FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));
- inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, src2w);
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, src1w));
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
FAIL_IF(!inst);
*inst = TEST_rm_r;
}
@@ -2091,25 +2055,29 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler,
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
}
else {
- /* This case is really difficult, since ecx itself may used for
- addressing, and we must ensure to work even in that case. */
+ /* This case is complex since ecx itself may be used for
+ addressing, and this case must be supported as well. */
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
-#else
- /* [esp+0] contains the flags. */
- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_PREF_SHIFT_REG, 0);
-#endif
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0);
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
FAIL_IF(!inst);
*inst |= mode;
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
-#else
- EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));
-#endif
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0);
EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
+#else
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ EMIT_MOV(compiler, TMP_REG2, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
+ FAIL_IF(!inst);
+ *inst = XCHG_r_rm;
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ *inst |= mode;
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
+#endif
}
return SLJIT_SUCCESS;
@@ -2168,54 +2136,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
compiler->mode32 = op & SLJIT_I32_OP;
#endif
- if (GET_OPCODE(op) >= SLJIT_MUL) {
- if (SLJIT_UNLIKELY(GET_FLAGS(op)))
- compiler->flags_saved = 0;
- else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
- FAIL_IF(emit_save_flags(compiler));
- }
+ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+ return SLJIT_SUCCESS;
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
- if (!GET_FLAGS(op)) {
- if (emit_lea_binary(compiler, op & SLJIT_KEEP_FLAGS, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)
+ if (!HAS_FLAGS(op)) {
+ if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)
return compiler->error;
}
- else
- compiler->flags_saved = 0;
- if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
- FAIL_IF(emit_save_flags(compiler));
return emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_ADDC:
- if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */
- FAIL_IF(emit_restore_flags(compiler, 1));
- else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS))
- FAIL_IF(emit_save_flags(compiler));
- if (SLJIT_UNLIKELY(GET_FLAGS(op)))
- compiler->flags_saved = 0;
return emit_cum_binary(compiler, ADC_r_rm, ADC_rm_r, ADC, ADC_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUB:
- if (!GET_FLAGS(op)) {
- if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, op & SLJIT_KEEP_FLAGS, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED)
+ if (!HAS_FLAGS(op)) {
+ if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED)
return compiler->error;
}
- else
- compiler->flags_saved = 0;
- if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
- FAIL_IF(emit_save_flags(compiler));
+
if (dst == SLJIT_UNUSED)
return emit_cmp_binary(compiler, src1, src1w, src2, src2w);
return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUBC:
- if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */
- FAIL_IF(emit_restore_flags(compiler, 1));
- else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS))
- FAIL_IF(emit_save_flags(compiler));
- if (SLJIT_UNLIKELY(GET_FLAGS(op)))
- compiler->flags_saved = 0;
return emit_non_cum_binary(compiler, SBB_r_rm, SBB_rm_r, SBB, SBB_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_MUL:
@@ -2232,13 +2177,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return emit_cum_binary(compiler, XOR_r_rm, XOR_rm_r, XOR, XOR_EAX_i32,
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SHL:
- return emit_shift_with_flags(compiler, SHL, GET_FLAGS(op),
+ return emit_shift_with_flags(compiler, SHL, HAS_FLAGS(op),
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_LSHR:
- return emit_shift_with_flags(compiler, SHR, GET_FLAGS(op),
+ return emit_shift_with_flags(compiler, SHR, HAS_FLAGS(op),
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_ASHR:
- return emit_shift_with_flags(compiler, SAR, GET_FLAGS(op),
+ return emit_shift_with_flags(compiler, SAR, HAS_FLAGS(op),
dst, dstw, src1, src1w, src2, src2w);
}
@@ -2249,7 +2194,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
{
CHECK_REG_INDEX(check_sljit_get_register_index(reg));
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- if (reg >= SLJIT_R3 && reg <= SLJIT_R6)
+ if (reg >= SLJIT_R3 && reg <= SLJIT_R8)
return -1;
#endif
return reg_map[reg];
@@ -2280,36 +2225,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
-/* Alignment + 2 * 16 bytes. */
-static sljit_s32 sse2_data[3 + (4 + 4) * 2];
+/* Alignment(3) + 4 * 16 bytes. */
+static sljit_s32 sse2_data[3 + (4 * 4)];
static sljit_s32 *sse2_buffer;
static void init_compiler(void)
{
+ /* Align to 16 bytes. */
sse2_buffer = (sljit_s32*)(((sljit_uw)sse2_data + 15) & ~0xf);
- /* Single precision constants. */
+
+ /* Single precision constants (each constant is 16 byte long). */
sse2_buffer[0] = 0x80000000;
sse2_buffer[4] = 0x7fffffff;
- /* Double precision constants. */
+ /* Double precision constants (each constant is 16 byte long). */
sse2_buffer[8] = 0;
sse2_buffer[9] = 0x80000000;
sse2_buffer[12] = 0xffffffff;
sse2_buffer[13] = 0x7fffffff;
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
- return SLJIT_IS_FPU_AVAILABLE;
-#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
- if (cpu_has_sse2 == -1)
- get_cpu_features();
- return cpu_has_sse2;
-#else /* SLJIT_DETECT_SSE2 */
- return 1;
-#endif /* SLJIT_DETECT_SSE2 */
-}
-
static sljit_s32 emit_sse2(struct sljit_compiler *compiler, sljit_u8 opcode,
sljit_s32 single, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w)
{
@@ -2350,7 +2284,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
- sljit_s32 dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
sljit_u8 *inst;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@@ -2363,7 +2297,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
*inst++ = GROUP_0F;
*inst = CVTTSD2SI_r_xm;
- if (dst_r == TMP_REG1 && dst != SLJIT_UNUSED)
+ if (dst & SLJIT_MEM)
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
return SLJIT_SUCCESS;
}
@@ -2407,7 +2341,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- compiler->flags_saved = 0;
if (!FAST_IS_REG(src1)) {
FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w));
src1 = TMP_FREG;
@@ -2456,7 +2389,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
return SLJIT_SUCCESS;
}
- if (SLOW_IS_REG(dst)) {
+ if (FAST_IS_REG(dst)) {
dst_r = dst;
if (dst != src)
FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src, srcw));
@@ -2554,11 +2487,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_label(compiler));
- /* We should restore the flags before the label,
- since other taken jumps has their own flags as well. */
- if (SLJIT_UNLIKELY(compiler->flags_saved))
- PTR_FAIL_IF(emit_restore_flags(compiler, 0));
-
if (compiler->last_label && compiler->last_label->size == compiler->size)
return compiler->last_label;
@@ -2581,15 +2509,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
struct sljit_jump *jump;
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
CHECK_PTR(check_sljit_emit_jump(compiler, type));
- if (SLJIT_UNLIKELY(compiler->flags_saved)) {
- if ((type & 0xff) <= SLJIT_JUMP)
- PTR_FAIL_IF(emit_restore_flags(compiler, 0));
- compiler->flags_saved = 0;
- }
-
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF_NULL(jump);
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
@@ -2609,10 +2530,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
PTR_FAIL_IF_NULL(inst);
*inst++ = 0;
- *inst++ = type + 4;
+ *inst++ = type + 2;
return jump;
}
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+#ifndef _WIN64
+#define IS_REG_CHANGED_BY_CALL(src, type) ((src) == SLJIT_R3)
+#else
+#define IS_REG_CHANGED_BY_CALL(src, type) ((src) == SLJIT_R2)
+#endif
+#endif
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
{
sljit_u8 *inst;
@@ -2624,12 +2553,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
CHECK_EXTRA_REGS(src, srcw, (void)0);
- if (SLJIT_UNLIKELY(compiler->flags_saved)) {
- if (type <= SLJIT_JUMP)
- FAIL_IF(emit_restore_flags(compiler, 0));
- compiler->flags_saved = 0;
- }
-
if (type >= SLJIT_CALL1) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
@@ -2640,11 +2563,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
if (src == SLJIT_MEM1(SLJIT_SP) && type >= SLJIT_CALL3)
srcw += sizeof(sljit_sw);
#endif
-#endif
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64)
- if (src == SLJIT_R2) {
- EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
- src = TMP_REG1;
+#else
+ if ((src & SLJIT_MEM) || IS_REG_CHANGED_BY_CALL(src, type)) {
+ EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
+ src = TMP_REG2;
}
#endif
FAIL_IF(call_with_args(compiler, type));
@@ -2667,7 +2589,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
FAIL_IF_NULL(inst);
*inst++ = 0;
- *inst++ = type + 4;
+ *inst++ = type + 2;
}
else {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@@ -2684,37 +2606,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src, sljit_sw srcw,
sljit_s32 type)
{
sljit_u8 *inst;
sljit_u8 cond_set = 0;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
sljit_s32 reg;
-#else
- /* CHECK_EXTRA_REGS migh overwrite these values. */
+#endif
+ /* ADJUST_LOCAL_OFFSET and CHECK_EXTRA_REGS might overwrite these values. */
sljit_s32 dst_save = dst;
sljit_sw dstw_save = dstw;
-#endif
CHECK_ERROR();
- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
- SLJIT_UNUSED_ARG(srcw);
-
- if (dst == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
CHECK_EXTRA_REGS(dst, dstw, (void)0);
- if (SLJIT_UNLIKELY(compiler->flags_saved))
- FAIL_IF(emit_restore_flags(compiler, op & SLJIT_KEEP_FLAGS));
type &= 0xff;
/* setcc = jcc + 0x10. */
cond_set = get_jump_code(type) + 0x10;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && dst == src) {
+ if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst)) {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 3);
FAIL_IF(!inst);
INC_SIZE(4 + 3);
@@ -2729,7 +2643,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
return SLJIT_SUCCESS;
}
- reg = (op == SLJIT_MOV && FAST_IS_REG(dst)) ? dst : TMP_REG1;
+ reg = (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG1;
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 4);
FAIL_IF(!inst);
@@ -2740,6 +2654,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
*inst++ = cond_set;
*inst++ = MOD_REG | reg_lmap[reg];
*inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R));
+ /* The movzx instruction does not affect flags. */
*inst++ = GROUP_0F;
*inst++ = MOVZX_r_rm8;
*inst = MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg];
@@ -2751,12 +2666,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
compiler->mode32 = GET_OPCODE(op) != SLJIT_MOV;
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
}
+
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
- return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REG1, 0);
-#else /* SLJIT_CONFIG_X86_64 */
+ return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
+
+#else
+ /* The SLJIT_CONFIG_X86_32 code path starts here. */
if (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) {
if (reg_map[dst] <= 4) {
/* Low byte is accessible. */
@@ -2810,8 +2728,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
return SLJIT_SUCCESS;
}
- if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && dst == src && reg_map[dst] <= 4) {
- SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R0] == 0, scratch_reg1_must_be_eax);
+ if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && reg_map[dst] <= 4) {
+ SLJIT_ASSERT(reg_map[SLJIT_R0] == 0);
+
if (dst != SLJIT_R0) {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1);
FAIL_IF(!inst);
@@ -2870,6 +2789,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
#endif /* SLJIT_CONFIG_X86_64 */
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8* inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ dst_reg &= ~SLJIT_I32_OP;
+
+ if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV) || (dst_reg >= SLJIT_R3 && dst_reg <= SLJIT_S3))
+ return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
+#else
+ if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV))
+ return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
+#endif
+
+ /* ADJUST_LOCAL_OFFSET is not needed. */
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = dst_reg & SLJIT_I32_OP;
+ dst_reg &= ~SLJIT_I32_OP;
+#endif
+
+ if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst++ = GROUP_0F;
+ *inst = get_jump_code(type & 0xff) - 0x40;
+ return SLJIT_SUCCESS;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
{
CHECK_ERROR();
@@ -2888,16 +2847,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
if (NOT_HALFWORD(offset)) {
FAIL_IF(emit_load_imm64(compiler, TMP_REG1, offset));
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
- SLJIT_ASSERT(emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED);
+ SLJIT_ASSERT(emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED);
return compiler->error;
#else
- return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0);
+ return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0);
#endif
}
#endif
if (offset != 0)
- return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
+ return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
return emit_mov(compiler, dst, dstw, SLJIT_SP, 0);
}
@@ -2910,7 +2869,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
#endif
CHECK_ERROR_PTR();
- CHECK_DYN_CODE_MOD(1);
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
@@ -2922,14 +2880,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
compiler->mode32 = 0;
- reg = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
if (emit_load_imm64(compiler, reg, init_value))
return NULL;
#else
- if (dst == SLJIT_UNUSED)
- dst = TMP_REG1;
-
if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value))
return NULL;
#endif
@@ -2949,82 +2904,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
+ SLJIT_UNUSED_ARG(executable_offset);
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- sljit_unaligned_store_sw((void*)addr, new_addr - (addr + 4));
+ sljit_unaligned_store_sw((void*)addr, new_target - (addr + 4) - (sljit_uw)executable_offset);
#else
- sljit_unaligned_store_sw((void*)addr, (sljit_sw) new_addr);
+ sljit_unaligned_store_sw((void*)addr, (sljit_sw) new_target);
#endif
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
+ SLJIT_UNUSED_ARG(executable_offset);
sljit_unaligned_store_sw((void*)addr, new_constant);
}
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_sse2_available(void)
-{
-#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
- if (cpu_has_sse2 == -1)
- get_cpu_features();
- return cpu_has_sse2;
-#else
- return 1;
-#endif
-}
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_cmov_available(void)
-{
- if (cpu_has_cmov == -1)
- get_cpu_features();
- return cpu_has_cmov;
-}
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_emit_cmov(struct sljit_compiler *compiler,
- sljit_s32 type,
- sljit_s32 dst_reg,
- sljit_s32 src, sljit_sw srcw)
-{
- sljit_u8* inst;
-
- CHECK_ERROR();
-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(sljit_x86_is_cmov_available());
- CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));
- CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);
- CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP));
- FUNCTION_CHECK_SRC(src, srcw);
-#endif
-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
- if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " x86_cmov%s %s%s, ",
- !(dst_reg & SLJIT_I32_OP) ? "" : ".i",
- jump_names[type & 0xff], JUMP_POSTFIX(type));
- sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP);
- fprintf(compiler->verbose, ", ");
- sljit_verbose_param(compiler, src, srcw);
- fprintf(compiler->verbose, "\n");
- }
-#endif
-
- ADJUST_LOCAL_OFFSET(src, srcw);
- CHECK_EXTRA_REGS(src, srcw, (void)0);
-
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- compiler->mode32 = dst_reg & SLJIT_I32_OP;
-#endif
- dst_reg &= ~SLJIT_I32_OP;
-
- if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
- src = TMP_REG1;
- srcw = 0;
- }
-
- inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw);
- FAIL_IF(!inst);
- *inst++ = GROUP_0F;
- *inst = get_jump_code(type & 0xff) - 0x40;
- return SLJIT_SUCCESS;
-}
diff --git a/pcre/sljit/sljitUtils.c b/pcre/sljit/sljitUtils.c
index ec5c321194a..9029db292c0 100644
--- a/pcre/sljit/sljitUtils.c
+++ b/pcre/sljit/sljitUtils.c
@@ -1,7 +1,7 @@
/*
* Stack-less Just-In-Time compiler
*
- * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -206,10 +206,7 @@ static sljit_sw sljit_page_align = 0;
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data)
{
struct sljit_stack *stack;
- union {
- void *ptr;
- sljit_uw uw;
- } base;
+ void *ptr;
#ifdef _WIN32
SYSTEM_INFO si;
#endif
@@ -233,29 +230,29 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
}
#endif
- /* Align limit and max_limit. */
- max_limit = (max_limit + sljit_page_align) & ~sljit_page_align;
-
stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
if (!stack)
return NULL;
+ /* Align max_limit. */
+ max_limit = (max_limit + sljit_page_align) & ~sljit_page_align;
+
#ifdef _WIN32
- base.ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
- if (!base.ptr) {
+ ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
+ if (!ptr) {
SLJIT_FREE(stack, allocator_data);
return NULL;
}
- stack->base = base.uw;
+ stack->max_limit = (sljit_u8 *)ptr;
+ stack->base = stack->max_limit + max_limit;
stack->limit = stack->base;
- stack->max_limit = stack->base + max_limit;
- if (sljit_stack_resize(stack, stack->base + limit)) {
+ if (sljit_stack_resize(stack, stack->base - limit)) {
sljit_free_stack(stack, allocator_data);
return NULL;
}
#else
#ifdef MAP_ANON
- base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
#else
if (dev_zero < 0) {
if (open_dev_zero()) {
@@ -263,15 +260,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
return NULL;
}
}
- base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
+ ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
#endif
- if (base.ptr == MAP_FAILED) {
+ if (ptr == MAP_FAILED) {
SLJIT_FREE(stack, allocator_data);
return NULL;
}
- stack->base = base.uw;
- stack->limit = stack->base + limit;
- stack->max_limit = stack->base + max_limit;
+ stack->max_limit = (sljit_u8 *)ptr;
+ stack->base = stack->max_limit + max_limit;
+ stack->limit = stack->base - limit;
#endif
stack->top = stack->base;
return stack;
@@ -279,53 +276,53 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
#undef PAGE_ALIGN
-SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack, void *allocator_data)
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
{
SLJIT_UNUSED_ARG(allocator_data);
#ifdef _WIN32
- VirtualFree((void*)stack->base, 0, MEM_RELEASE);
+ VirtualFree((void*)stack->max_limit, 0, MEM_RELEASE);
#else
- munmap((void*)stack->base, stack->max_limit - stack->base);
+ munmap((void*)stack->max_limit, stack->base - stack->max_limit);
#endif
SLJIT_FREE(stack, allocator_data);
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
+SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_limit)
{
sljit_uw aligned_old_limit;
sljit_uw aligned_new_limit;
- if ((new_limit > stack->max_limit) || (new_limit < stack->base))
+ if ((new_limit < stack->max_limit) || (new_limit >= stack->base))
return -1;
#ifdef _WIN32
- aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
- aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
+ aligned_new_limit = (sljit_uw)new_limit & ~sljit_page_align;
+ aligned_old_limit = ((sljit_uw)stack->limit) & ~sljit_page_align;
if (aligned_new_limit != aligned_old_limit) {
- if (aligned_new_limit > aligned_old_limit) {
- if (!VirtualAlloc((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_COMMIT, PAGE_READWRITE))
+ if (aligned_new_limit < aligned_old_limit) {
+ if (!VirtualAlloc((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_COMMIT, PAGE_READWRITE))
return -1;
}
else {
- if (!VirtualFree((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_DECOMMIT))
+ if (!VirtualFree((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_DECOMMIT))
return -1;
}
}
stack->limit = new_limit;
return 0;
#else
- if (new_limit >= stack->limit) {
+ if (new_limit <= stack->limit) {
stack->limit = new_limit;
return 0;
}
- aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
- aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
+ aligned_new_limit = (sljit_uw)new_limit & ~sljit_page_align;
+ aligned_old_limit = ((sljit_uw)stack->limit) & ~sljit_page_align;
/* If madvise is available, we release the unnecessary space. */
#if defined(MADV_DONTNEED)
- if (aligned_new_limit < aligned_old_limit)
- madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED);
+ if (aligned_new_limit > aligned_old_limit)
+ madvise((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MADV_DONTNEED);
#elif defined(POSIX_MADV_DONTNEED)
- if (aligned_new_limit < aligned_old_limit)
- posix_madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, POSIX_MADV_DONTNEED);
+ if (aligned_new_limit > aligned_old_limit)
+ posix_madvise((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, POSIX_MADV_DONTNEED);
#endif
stack->limit = new_limit;
return 0;
diff --git a/pcre/testdata/testinput1 b/pcre/testdata/testinput1
index 93abab3c851..5c23f41fa81 100644
--- a/pcre/testdata/testinput1
+++ b/pcre/testdata/testinput1
@@ -5739,4 +5739,7 @@ AbcdCBefgBhiBqz
/(?=.*X)X$/
\ X
+/X+(?#comment)?/
+ >XXX<
+
/-- End of testinput1 --/
diff --git a/pcre/testdata/testinput12 b/pcre/testdata/testinput12
index 944be6943f5..89ed4564bcd 100644
--- a/pcre/testdata/testinput12
+++ b/pcre/testdata/testinput12
@@ -104,4 +104,6 @@ and a couple of things that are different with JIT. --/
/(.|.)*?bx/
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabax
+/((?(?!))x)(?'name')(?1)/S++
+
/-- End of testinput12 --/
diff --git a/pcre/testdata/testinput15 b/pcre/testdata/testinput15
index 83e26773471..c065105b1ec 100644
--- a/pcre/testdata/testinput15
+++ b/pcre/testdata/testinput15
@@ -363,4 +363,7 @@ correctly, but that messes up comparisons). --/
/abc/89
+//8+L
+ \xf1\xad\xae\xae
+
/-- End of testinput15 --/
diff --git a/pcre/testdata/testinput8 b/pcre/testdata/testinput8
index 7f8fa8292c5..e931410479f 100644
--- a/pcre/testdata/testinput8
+++ b/pcre/testdata/testinput8
@@ -4845,4 +4845,7 @@
aaa\D
a\D
+/(02-)?[0-9]{3}-[0-9]{3}/
+ 02-123-123
+
/-- End of testinput8 --/
diff --git a/pcre/testdata/testoutput1 b/pcre/testdata/testoutput1
index a2b3cffe9d4..eff8ecc948c 100644
--- a/pcre/testdata/testoutput1
+++ b/pcre/testdata/testoutput1
@@ -9442,4 +9442,8 @@ No match
\ X
0: X
+/X+(?#comment)?/
+ >XXX<
+ 0: X
+
/-- End of testinput1 --/
diff --git a/pcre/testdata/testoutput12 b/pcre/testdata/testoutput12
index 87911086f49..7632c4e5801 100644
--- a/pcre/testdata/testoutput12
+++ b/pcre/testdata/testoutput12
@@ -201,4 +201,6 @@ No match, mark = m (JIT)
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabax
Error -8 (match limit exceeded)
+/((?(?!))x)(?'name')(?1)/S++
+
/-- End of testinput12 --/
diff --git a/pcre/testdata/testoutput15 b/pcre/testdata/testoutput15
index bad2807c2fd..e4e123c3983 100644
--- a/pcre/testdata/testoutput15
+++ b/pcre/testdata/testoutput15
@@ -1136,4 +1136,9 @@ Failed: setting UTF is disabled by the application at offset 0
/abc/89
Failed: setting UTF is disabled by the application at offset 0
+//8+L
+ \xf1\xad\xae\xae
+ 0:
+ 0+ \x{6dbae}
+
/-- End of testinput15 --/
diff --git a/pcre/testdata/testoutput8 b/pcre/testdata/testoutput8
index 17b667a980c..4984376d3c8 100644
--- a/pcre/testdata/testoutput8
+++ b/pcre/testdata/testoutput8
@@ -7801,4 +7801,8 @@ No match
** Show all captures ignored after DFA matching
0: a
+/(02-)?[0-9]{3}-[0-9]{3}/
+ 02-123-123
+ 0: 02-123-123
+
/-- End of testinput8 --/
From 7f5a8f176ac59f0a15fb3723b5b2ab47b4fbe9e0 Mon Sep 17 00:00:00 2001
From: Alexey Botchkov
Date: Tue, 25 Jul 2017 10:57:25 +0400
Subject: [PATCH 084/101] MDEV-12915 ST_Centroid does not return the same
result than MySQL.
Calculation of the polygon's centroid fixed.
---
mysql-test/r/gis.result | 8 +++---
mysql-test/suite/archive/archive_gis.result | 4 +--
mysql-test/suite/innodb/r/innodb_gis.result | 4 +--
sql/spatial.cc | 27 ++++++++++++++++-----
4 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index f029542e717..f77cd4d14bf 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -333,8 +333,8 @@ fid IsClosed(g)
116 0
SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
fid AsText(Centroid(g))
-117 POINT(55.58852775304245 17.426536064113982)
-118 POINT(55.58852775304245 17.426536064113982)
+117 POINT(57.98031067576927 17.854754130800433)
+118 POINT(57.98031067576927 17.854754130800433)
119 POINT(2 2)
SELECT fid, Area(g) FROM gis_multi_polygon;
fid Area(g)
@@ -684,11 +684,11 @@ insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363
select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
t1 where object_id=85998;
object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo))
-85998 MULTIPOLYGON 1 POINT(115.31877315203187 -36.23747282102153)
+85998 MULTIPOLYGON 1 POINT(115.2970604672862 -36.23335610879993)
select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
t1 where object_id=85984;
object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo))
-85984 MULTIPOLYGON 1 POINT(-114.87787186923313 36.33101763469059)
+85984 MULTIPOLYGON 1 POINT(-114.86854472054372 36.34725218253213)
drop table t1;
create table t1 (fl geometry not null);
insert into t1 values (1);
diff --git a/mysql-test/suite/archive/archive_gis.result b/mysql-test/suite/archive/archive_gis.result
index 97f48407db2..5593b53f7c3 100644
--- a/mysql-test/suite/archive/archive_gis.result
+++ b/mysql-test/suite/archive/archive_gis.result
@@ -326,8 +326,8 @@ fid IsClosed(g)
116 0
SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid;
fid AsText(Centroid(g))
-117 POINT(55.58852775304245 17.426536064113982)
-118 POINT(55.58852775304245 17.426536064113982)
+117 POINT(57.98031067576927 17.854754130800433)
+118 POINT(57.98031067576927 17.854754130800433)
119 POINT(2 2)
SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid;
fid Area(g)
diff --git a/mysql-test/suite/innodb/r/innodb_gis.result b/mysql-test/suite/innodb/r/innodb_gis.result
index 21c1234d7d3..f683195ac15 100644
--- a/mysql-test/suite/innodb/r/innodb_gis.result
+++ b/mysql-test/suite/innodb/r/innodb_gis.result
@@ -326,8 +326,8 @@ fid IsClosed(g)
116 0
SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid;
fid AsText(Centroid(g))
-117 POINT(55.58852775304245 17.426536064113982)
-118 POINT(55.58852775304245 17.426536064113982)
+117 POINT(57.98031067576927 17.854754130800433)
+118 POINT(57.98031067576927 17.854754130800433)
119 POINT(2 2)
SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid;
fid Area(g)
diff --git a/sql/spatial.cc b/sql/spatial.cc
index bfe302f332e..b03a8b6da07 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -1150,8 +1150,8 @@ int Gis_polygon::centroid_xy(double *x, double *y) const
uint32 n_points, org_n_points;
double prev_x, prev_y;
double cur_area= 0;
- double cur_cx= 0;
- double cur_cy= 0;
+ double cur_cx= 0, cur_cy= 0;
+ double sum_cx= 0, sum_cy= 0;
if (no_data(data, 4))
return 1;
@@ -1165,17 +1165,32 @@ int Gis_polygon::centroid_xy(double *x, double *y) const
while (--n_points) // One point is already read
{
double tmp_x, tmp_y;
+ double loc_area;
get_point(&tmp_x, &tmp_y, data);
data+= POINT_DATA_SIZE;
- cur_area+= (prev_x + tmp_x) * (prev_y - tmp_y);
+ loc_area= prev_x * tmp_y - tmp_x * prev_y;
+ cur_area+= loc_area;
cur_cx+= tmp_x;
cur_cy+= tmp_y;
+ sum_cx+= (prev_x + tmp_x) * loc_area;
+ sum_cy+= (prev_y + tmp_y) * loc_area;
+
prev_x= tmp_x;
prev_y= tmp_y;
}
- cur_area= fabs(cur_area) / 2;
- cur_cx= cur_cx / (org_n_points - 1);
- cur_cy= cur_cy / (org_n_points - 1);
+
+ if (fabs(cur_area) > 1e-10)
+ {
+ cur_cx= sum_cx / cur_area / 3.0;
+ cur_cy= sum_cy / cur_area / 3.0;
+ }
+ else
+ {
+ cur_cx= cur_cx / (org_n_points - 1);
+ cur_cy= cur_cy / (org_n_points - 1);
+ }
+
+ cur_area= fabs(cur_area);
if (!first_loop)
{
From 3d2067460eb028666f40021a371f9b2cbfd2ce9b Mon Sep 17 00:00:00 2001
From: Alexey Botchkov
Date: Tue, 25 Jul 2017 15:51:07 +0400
Subject: [PATCH 085/101] MDEV-12915 ST_Centroid does not return the same
result than MySQL.
Test fixed for IA64.
---
mysql-test/t/gis.test | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index fe7b8ff7383..4192a3284b7 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -356,15 +356,15 @@ insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363
36.248666,-115.263639 36.247466,-115.263839 36.252766,-115.261439
36.252666,-115.261439 36.247366,-115.247239 36.247066)))'));
-# Expected result is 115.31877315203187, but IA64 returns 115.31877315203188
-# due to fused multiply-add instructions.
---replace_result 115.31877315203188 115.31877315203187
+# Expected results are 115.2970604672862 and 36.23335610879993, but IA64 returns
+# slightly different values due to fused multiply-add instructions.
+--replace_result 115.29706047613604 115.2970604672862 36.23335611157958 36.23335610879993
select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
t1 where object_id=85998;
-# Expected result is 36.3310176346905, but IA64 returns 36.3310176346904
+# Expected result is 36.34725218253213, but IA64 returns 36.34725217627852
# due to fused multiply-add instructions.
---replace_result 36.3310176346904 36.3310176346905 -114.87787186923326 -114.87787186923313 36.33101763469053 36.33101763469059 36.33101763469043 36.33101763469059
+--replace_result 36.34725217627852 36.34725218253213 -114.86854470090232 -114.86854472054372
select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
t1 where object_id=85984;
From 60343871a73220e2a44d1cebb36e4d109c52c11c Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Fri, 13 Nov 2015 17:53:16 +0100
Subject: [PATCH 086/101] MDEV-8453 Alter table not returning engine errors
remove ~15 years old print_lock_error() function, use
handler::print_error() instead
Backport from 10.1
---
.../r/engine_error_in_alter-8453.result | 6 +++
mysql-test/t/engine_error_in_alter-8453.test | 11 ++++++
sql/handler.cc | 4 ++
sql/lock.cc | 37 ++-----------------
4 files changed, 24 insertions(+), 34 deletions(-)
create mode 100644 mysql-test/r/engine_error_in_alter-8453.result
create mode 100644 mysql-test/t/engine_error_in_alter-8453.test
diff --git a/mysql-test/r/engine_error_in_alter-8453.result b/mysql-test/r/engine_error_in_alter-8453.result
new file mode 100644
index 00000000000..c5a3375f33c
--- /dev/null
+++ b/mysql-test/r/engine_error_in_alter-8453.result
@@ -0,0 +1,6 @@
+create table t1 (a int, b int);
+set debug_dbug='+d,external_lock_failure';
+alter table t1 add column c int;
+ERROR HY000: Got error 168 'KABOOM!' from MyISAM
+set debug_dbug='';
+drop table t1;
diff --git a/mysql-test/t/engine_error_in_alter-8453.test b/mysql-test/t/engine_error_in_alter-8453.test
new file mode 100644
index 00000000000..c4600ec07fe
--- /dev/null
+++ b/mysql-test/t/engine_error_in_alter-8453.test
@@ -0,0 +1,11 @@
+#
+# MDEV-8453 Alter table not returning engine errors
+#
+--source include/have_debug.inc
+
+create table t1 (a int, b int);
+set debug_dbug='+d,external_lock_failure';
+--error ER_GET_ERRMSG
+alter table t1 add column c int;
+set debug_dbug='';
+drop table t1;
diff --git a/sql/handler.cc b/sql/handler.cc
index e51f17f1712..2696d69bfcf 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -3650,6 +3650,8 @@ void handler::print_error(int error, myf errflag)
*/
bool handler::get_error_message(int error, String* buf)
{
+ DBUG_EXECUTE_IF("external_lock_failure",
+ buf->set_ascii(STRING_WITH_LEN("KABOOM!")););
return FALSE;
}
@@ -5944,6 +5946,8 @@ int handler::ha_external_lock(THD *thd, int lock_type)
MYSQL_TABLE_LOCK_WAIT(m_psi, PSI_TABLE_EXTERNAL_LOCK, lock_type,
{ error= external_lock(thd, lock_type); })
+ DBUG_EXECUTE_IF("external_lock_failure", error= HA_ERR_GENERIC;);
+
if (error == 0 || lock_type == F_UNLCK)
{
m_lock_type= lock_type;
diff --git a/sql/lock.cc b/sql/lock.cc
index 29afcc8f578..3354da2640b 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -92,7 +92,6 @@ extern HASH open_cache;
static int lock_external(THD *thd, TABLE **table,uint count);
static int unlock_external(THD *thd, TABLE **table,uint count);
-static void print_lock_error(int error, TABLE *);
/* Map the return value of thr_lock to an error from errmsg.txt */
static int thr_lock_errno_to_mysql[]=
@@ -358,7 +357,7 @@ static int lock_external(THD *thd, TABLE **tables, uint count)
if ((error=(*tables)->file->ha_external_lock(thd,lock_type)))
{
- print_lock_error(error, *tables);
+ (*tables)->file->print_error(error, MYF(0));
while (--i)
{
tables--;
@@ -675,8 +674,8 @@ static int unlock_external(THD *thd, TABLE **table,uint count)
(*table)->current_lock = F_UNLCK;
if ((error=(*table)->file->ha_external_lock(thd, F_UNLCK)))
{
- error_code=error;
- print_lock_error(error_code, *table);
+ error_code= error;
+ (*table)->file->print_error(error, MYF(0));
}
}
table++;
@@ -898,36 +897,6 @@ bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type,
}
-static void print_lock_error(int error, TABLE *table)
-{
- int textno;
- DBUG_ENTER("print_lock_error");
-
- switch (error) {
- case HA_ERR_LOCK_WAIT_TIMEOUT:
- textno=ER_LOCK_WAIT_TIMEOUT;
- break;
- case HA_ERR_READ_ONLY_TRANSACTION:
- textno=ER_READ_ONLY_TRANSACTION;
- break;
- case HA_ERR_LOCK_DEADLOCK:
- textno=ER_LOCK_DEADLOCK;
- break;
- case HA_ERR_WRONG_COMMAND:
- my_error(ER_ILLEGAL_HA, MYF(0), table->file->table_type(),
- table->s->db.str, table->s->table_name.str);
- DBUG_VOID_RETURN;
- default:
- textno=ER_CANT_LOCK;
- break;
- }
-
- my_error(textno, MYF(0), error);
-
- DBUG_VOID_RETURN;
-}
-
-
/****************************************************************************
Handling of global read locks
From e6e23c0d4916e08a7ca6b1c68f5e8e63bb1cff83 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik
Date: Sat, 19 Mar 2016 19:40:25 +0100
Subject: [PATCH 087/101] MDEV-9739 Assertion `m_status == DA_ERROR || m_status
== DA_OK' failed in Diagnostics_area::message() ; connect.xml* tests fail in
buildbot
---
sql/sql_show.cc | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 9a743388149..a3d834b0e42 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -5314,7 +5314,10 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
HA_STATUS_TIME |
HA_STATUS_VARIABLE_EXTRA |
HA_STATUS_AUTO)) != 0)
+ {
+ file->print_error(info_error, MYF(0));
goto err;
+ }
enum row_type row_type = file->get_row_type();
switch (row_type) {
From fd47b9639d818a9001076c603931c134ce1d801c Mon Sep 17 00:00:00 2001
From: Elena Stepanova
Date: Mon, 31 Jul 2017 03:26:43 +0300
Subject: [PATCH 088/101] List of unstable tests for 10.0.32 release
---
mysql-test/unstable-tests | 130 +++++++++++++++++++++-----------------
1 file changed, 73 insertions(+), 57 deletions(-)
diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests
index 0a2d5a85e51..868a6c90685 100644
--- a/mysql-test/unstable-tests
+++ b/mysql-test/unstable-tests
@@ -23,47 +23,57 @@
#
##############################################################################
+main.alter_table_online : Modified in 10.0.32
+main.binary_to_hex : Modified in 10.0.32
+main.bootstrap : Modified in 10.0.32
+main.count_distinct : Modified in 10.0.32
main.count_distinct2 : MDEV-11768 - timeout
main.create_delayed : MDEV-10605 - failed with timeout
+main.ctype_ucs : Modified in 10.0.32
main.debug_sync : MDEV-10607 - internal error
main.derived_opt : MDEV-11768 - timeout
-main.derived_view : Modified in 10.0.31
-main.events_2 : Modified in 10.0.31
+main.engine_error_in_alter-8453 : Added in 10.0.32
main.events_slowlog : MDEV-12821 - wrong result
-main.func_regexp_pcre : Modified in 10.0.31
-main.gis : Modified in 10.0.31
+main.func_concat : Modified in 10.0.32
+main.func_crypt : Modified in 10.0.32
+main.func_regexp_pcre : MDEV-13412 - crash, wrong result; modified in 10.0.32
+main.gis : MDEV-13411 - wrong result on P8; modified in 10.0.32
+main.gis-alter_table_online : Added in 10.0.32
+main.gis-rt-precise : Modified in 10.0.32
+main.group_by : Modified in 10.0.32
main.host_cache_size_functionality : MDEV-10606 - sporadic failure on shutdown
main.index_intersect_innodb : MDEV-10643 - failed with timeout
main.index_merge_innodb : MDEV-7142 - wrong result
main.innodb_mysql_lock : MDEV-7861 - sporadic lock detection failure
-main.loaddata : Modified in 10.0.31
-main.log_tables-big : Modified in 10.0.31
+main.join_outer : Modified in 10.0.32
+main.loadxml : Data file modified in 10.0.32
+main.log_tables-big : MDEV-13408 - wrong result
main.mdev-504 : MDEV-10607 - sporadic "can't connect"
main.mdev375 : MDEV-10607 - sporadic "can't connect"
main.merge : MDEV-10607 - sporadic "can't connect"
-main.mysqld--help : Modified in 10.0.31
-main.mysqldump : Modified in 10.0.31
+main.mysql : Modified in 10.0.32
main.mysqlhotcopy_myisam : MDEV-10995 - test hangs on debug build
-main.mysqltest : MDEV-9269 - fails on Alpha
+main.mysqltest : MDEV-9269 - fails on Alpha; modified in 10.0.32
+main.mysql_upgrade : Modified in 10.0.32
main.ps : MDEV-11017 - sporadic wrong Prepared_stmt_count
+main.read_only : Modified in 10.0.32
main.show_explain : MDEV-10674 - wrong result
main.sp_notembedded : MDEV-10607 - internal error
main.sp-security : MDEV-10607 - sporadic "can't connect"
-main.subselect4 : Modified in 10.0.31
-main.subselect_exists2in : Modified in 10.0.31
-main.subselect_innodb : MDEV-10614 - sporadic wrong results; modified in 10.0.31
-main.subselect_mat_cost_bugs : Modified in 10.0.31
-main.subselect_sj : Modified in 10.0.31
-main.subselect_sj_mat : Modified in 10.0.31
-main.subselect_sj2_mat : Modified in 10.0.31
-main.symlink : Modified in 10.0.31
-main.symlink-myisam-11902 : Modified in 10.0.31
-main.view : Modified in 10.0.31
+main.subselect : Modified in 10.0.32
+main.subselect_innodb : MDEV-10614 - sporadic wrong results
+main.subselect_mat_cost_bugs : Modified in 10.0.32
+main.subselect_nulls : Modified in 10.0.32
+main.subselect_sj2_mat : Modified in 10.0.32
+main.subselect_sj_mat : MOdified in 10.0.32
+main.symlink-aria-11902 : MDEV-12215 - Wrong error number
+main.symlink-myisam-11902 : MDEV-12215 - Wrong error number
+main.union : Modified in 10.0.32
+main.view : Modified in 10.0.32
main.xa : MDEV-11769 - lock wait timeout
#----------------------------------------------------------------
-archive.archive-big : MDEV-10615 - table is marked as crashed
archive.archive_bitfield : MDEV-11771 - table is marked as crashed
archive.archive_symlink : MDEV-12170 - unexpected error on rmdir
archive.discover : MDEV-10510 - table is marked as crashed
@@ -71,17 +81,21 @@ archive.mysqlhotcopy_archive : MDEV-10995 - test hangs on debug build
#----------------------------------------------------------------
-binlog.binlog_commit_wait : MDEV-10150 - Error: too much time elapsed
-binlog.binlog_xa_recover : MDEV-8517 - Extra checkpoint
+binlog.binlog_commit_wait : MDEV-10150 - Error: too much time elapsed
+binlog.binlog_unsafe : Modified in 10.0.32
+binlog.binlog_xa_recover : MDEV-8517 - Extra checkpoint
#----------------------------------------------------------------
-connect.jdbc_new : Modified in 10.0.31
-connect.tbl : MDEV-9844, MDEV-10179 - sporadic crashes, valgrind warnings, wrong results
-
-#----------------------------------------------------------------
-
-csv.read_only : Added in 10.0.31
+connect.drop-open-error : Added in 10.0.32
+connect.grant2 : Modified in 10.0.32
+connect.infoschema-9739 : Added in 10.0.32
+connect.json : Sporadic wrong result, tentative fix in 10.0.32
+connect.mysql_new : Modified in 10.0.32
+connect.odbc_firebird : Added in 10.0.32
+connect.secure_file_priv : Modified in 10.0.32
+connect.tbl : MDEV-9844, MDEV-10179 - sporadic crashes, valgrind warnings, wrong results
+connect.zip : Sporadic wrong result, tentative fix expected in 10.0.32
#----------------------------------------------------------------
@@ -90,6 +104,7 @@ engines/rr_trx.* : MDEV-10998 - tests not maintained
#----------------------------------------------------------------
federated.federatedx : MDEV-10617 - Wrong checksum, timeouts
+federated.federated_bug_35333 : MDEV-13410 - Wrong result
federated.federated_innodb : MDEV-10617, MDEV-10417 - Wrong checksum, timeouts, fails on Mips
federated.federated_partition : MDEV-10417 - Fails on Mips
federated.federated_transactions : MDEV-10617, MDEV-10417 - Wrong checksum, timeouts, fails on Mips
@@ -103,19 +118,28 @@ funcs_2/charset.* : MDEV-10999 - test not maintained
#----------------------------------------------------------------
-innodb.autoinc_debug : Added in 10.0.31
innodb.binlog_consistent : MDEV-10618 - Server fails to start
+innodb.drop_table_background : MDEV-13407 - Tablespace exists; added in 10.0.32
innodb.group_commit_crash_no_optimize_thread : MDEV-11770 - checksum mismatch
-innodb.innodb-alter-debug : Added in 10.0.31
-innodb.innodb-alter-nullable : Added in 10.0.31
-innodb.innodb-alter-table : MDEV-10619 - Testcase timeout
-innodb.innodb_bug14676111 : Modified in 10.0.31
+innodb.innodb-alter-debug : Modified in 10.0.32
+innodb.innodb-alter-discard : Modified in 10.0.32
+innodb.innodb-alter-nullable : Modified in 10.0.32
+innodb.innodb-alter-table : MDEV-10619 - Testcase timeout; modified in 10.0.32
+innodb.innodb-alter-tempfile : Modified in 10.0.32
innodb.innodb_bug30423 : MDEV-7311 - Wrong number of rows in the plan
-innodb.innodb-index-online-norebuild : Added in 10.0.31
-innodb.log_file_size : Modified in 10.0.31
+innodb.innodb-get-fk : Modified in 10.0.32
innodb.innodb_monitor : MDEV-10939 - Testcase timeout
+innodb.log_file_size : Modified in 10.0.32
+innodb.row_format_redundant : Added in 10.0.32
+innodb.table_flags : Added in 10.0.32
-innodb_fts.innodb_fts_stopword_charset : MDEV-12052 - Crash on shutdown; modified in 10.0.31
+innodb_zip.innodb_bug36169 : Modified in 10.0.32
+innodb_zip.innodb_bug36172 : Modified in 10.0.32
+innodb_zip.innodb_bug52745 : Modified in 10.0.32
+innodb_zip.innodb_bug53591 : Modified in 10.0.32
+innodb_zip.innodb_bug56680 : Modified in 10.0.32
+innodb_zip.innodb-create-options : Modified in 10.0.32
+innodb_zip.innodb-zip : Modified in 10.0.32
#----------------------------------------------------------------
@@ -129,17 +153,16 @@ mroonga/storage.index_multiple_column_unique_date_order_32bit_desc : Wrong resul
#----------------------------------------------------------------
multi_source.gtid : MDEV-10417 - Fails on Mips
+multi_source.info_logs : MDEV-10042 - Wrong result
multi_source.multisource : MDEV-10417 - Fails on Mips
multi_source.simple : MDEV-4633 - Wrong slave status output
multi_source.status_vars : MDEV-4632 - failed while waiting for Slave_received_heartbeats
#----------------------------------------------------------------
-myisam_debug : Modified in 10.0.31
-
-#----------------------------------------------------------------
-
+parts.longname : Added in 10.0.32
parts.partition_exch_qa_10 : MDEV-11765 - wrong result
+parts.quoting : Added in 10.0.32
#----------------------------------------------------------------
@@ -148,7 +171,6 @@ perfschema.func_mutex : MDEV-5708 - fails for s390x
perfschema.hostcache_ipv6_ssl : MDEV-10696 - crash on shutdown
perfschema.socket_summary_by_event_name_func : MDEV-10622 - Socket summary tables do not match
perfschema.stage_mdl_procedure : MDEV-11545 - Wrong result
-perfschema.start_server_1_digest : Added in 10.0.31
perfschema_stress.* : MDEV-10996 - tests not maintained
@@ -161,9 +183,12 @@ plugins.thread_pool_server_audit : MDEV-9562 - crashes on sol10-sparc
#----------------------------------------------------------------
roles.create_and_grant_role : MDEV-11772 - wrong result
+roles.current_role_view-12666 : Added in 10.0.32
+roles.show_create_database-10463 : Added in 10.0.32
#----------------------------------------------------------------
+rpl.circular_serverid0 : Added in 10.0.32
rpl.last_insert_id : MDEV-10625 - warnings in error log
rpl.rpl_auto_increment : MDEV-10417 - Fails on Mips
rpl.rpl_auto_increment_bug45679 : MDEV-10417 - Fails on Mips
@@ -180,9 +205,12 @@ rpl.rpl_insert_delayed : MDEV-9329 - Fails on Ubuntu/s390x
rpl.rpl_invoked_features : MDEV-10417 - Fails on Mips
rpl.rpl_mdev6020 : MDEV-10630, MDEV-10417 - Timeouts, fails on Mips
rpl.rpl_parallel : MDEV-10653 - Timeouts
+rpl.rpl_parallel_mdev6589 : MDEV-12979 - Assertion failure
rpl.rpl_parallel_temptable : MDEV-10356 - Crash in close_thread_tables
rpl.rpl_partition_innodb : MDEV-10417 - Fails on Mips
+rpl.rpl_reset_slave_fail : Added in 10.0.32
rpl.rpl_row_basic_11bugs : MDEV-12171 - Server failed to start
+rpl.rpl_row_index_choice : MDEV-13409 - Server crash
rpl.rpl_row_sp001 : MDEV-9329 - Fails on Ubuntu/s390x
rpl.rpl_semi_sync : MDEV-11220 - Wrong result
rpl.rpl_semi_sync_uninstall_plugin : MDEV-7140 - Wrong plugin status
@@ -219,41 +247,29 @@ stress.ddl_innodb : MDEV-10635 - Testcase timeout
sys_vars.autocommit_func2 : MDEV-9329 - Fails on Ubuntu/s390x
sys_vars.innodb_buffer_pool_dump_pct_basic : MDEV-10651 - sporadic failure on file_exists
-sys_vars.innodb_status_output_basic : MDEV-12174 - Timeout
+sys_vars.innodb_sched_priority_cleaner_basic : Modified in 10.0.32
sys_vars.thread_cache_size_func : MDEV-11775 - wrong result
#----------------------------------------------------------------
-tokudb.background_job_manager : Modified in 10.0.31
-tokudb.bug-1657908 : Added in 10.0.31
-tokudb.card_auto_analyze_lots : Modified in 10.0.31
tokudb.change_column_all_1000_10 : MDEV-12640 - Lost connection during query
tokudb.change_column_bin : MDEV-12640 - Lost connection during query
tokudb.change_column_char : MDEV-12822 - Lost connection during query
tokudb.cluster_filter_unpack_varchar : MDEV-10636 - Wrong execution plan
-tokudb.dir_cmd : Added in 10.0.31
tokudb.dir_per_db : MDEV-11537 - wrong result
tokudb.dir_per_db_rename_to_nonexisting_schema : MDEV-12823 - Valgrind
tokudb.hotindex-update-1 : MDEV-12640 - Lost connection during query
-tokudb.i_s_tokudb_lock_waits_timeout : Modified in 10.0.31
-tokudb.i_s_tokudb_locks : Modified in 10.0.31
+tokudb.locks-select-update-1 : MDEV-13406 - Lock wait timeout
tokudb.rows-32m-rand-insert : MDEV-12640 - Lost connection during query
tokudb.rows-32m-seq-insert : MDEV-12640 - Lost connection during query
tokudb_backup.* : MDEV-11001 - tests don't work
-tokudb_backup.backup_master_info : Added in 10.0.31
-tokudb_backup.backup_master_state : Added in 10.0.31
-tokudb_backup.empty_slave_info_file : Added in 10.0.31
-tokudb_backup.innodb_use_native_aio_enabled : Added in 10.0.31
-tokudb_backup.rpl_safe_slave : Added in 10.0.31
-tokudb_backup.rpl_tokudb_commit_sync : Added in 10.0.31
-
tokudb_bugs.checkpoint_lock : MDEV-10637 - Wrong processlist output
tokudb_bugs.checkpoint_lock_3 : MDEV-10637 - Wrong processlist output
-tokudb_bugs.db233 : Modified in 10.0.31
+tokudb_bugs.frm_store : MDEV-12823 - Valgrind
tokudb_bugs.frm_store2 : MDEV-12823 - Valgrind
-tokudb_bugs.leak172 : Modified in 10.0.31
+tokudb_bugs.frm_store3 : MDEV-12823 - Valgrind
tokudb_bugs.xa : MDEV-11804 - Lock wait timeout
tokudb_rpl.* : MDEV-11001 - tests don't work
From 3772516391b24fcbefac612b07a8502e6afdc00f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Mon, 31 Jul 2017 00:31:23 +0300
Subject: [PATCH 089/101] Update innodb test result post print_lock_error
change
---
mysql-test/suite/innodb/r/innodb-get-fk.result | 2 +-
mysql-test/suite/innodb/t/innodb-get-fk.test | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/mysql-test/suite/innodb/r/innodb-get-fk.result b/mysql-test/suite/innodb/r/innodb-get-fk.result
index f34fb8bcb67..ee17f262854 100644
--- a/mysql-test/suite/innodb/r/innodb-get-fk.result
+++ b/mysql-test/suite/innodb/r/innodb-get-fk.result
@@ -27,7 +27,7 @@ CONSTRAINT `fk_crewRoleAssigned_crewId` FOREIGN KEY (`crew_id`) REFERENCES `repr
CONSTRAINT `fk_crewRoleAssigned_pilotId` FOREIGN KEY (`crew_id`) REFERENCES `repro`.`pilot` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB COMMENT="This is a comment about tables";
ALTER TABLE `repro`.`crew_role_assigned` COMMENT = 'innodb_read_only';
-ERROR HY000: Can't lock file (errno: 165 "Table is read only")
+ERROR HY000: Table 'crew_role_assigned' is read only
SHOW CREATE TABLE `repro`.`crew_role_assigned`;
Table Create Table
crew_role_assigned CREATE TABLE `crew_role_assigned` (
diff --git a/mysql-test/suite/innodb/t/innodb-get-fk.test b/mysql-test/suite/innodb/t/innodb-get-fk.test
index c1ab54fab45..339a7968623 100644
--- a/mysql-test/suite/innodb/t/innodb-get-fk.test
+++ b/mysql-test/suite/innodb/t/innodb-get-fk.test
@@ -36,7 +36,7 @@ CONSTRAINT `fk_crewRoleAssigned_pilotId` FOREIGN KEY (`crew_id`) REFERENCES `rep
-- let $restart_parameters=--innodb-read-only
-- source include/restart_mysqld.inc
---error ER_CANT_LOCK
+--error ER_OPEN_AS_READONLY
ALTER TABLE `repro`.`crew_role_assigned` COMMENT = 'innodb_read_only';
SHOW CREATE TABLE `repro`.`crew_role_assigned`;
From e075c5b491b8e9030589cdf5d9aa5222e9cd1bc1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Mon, 31 Jul 2017 00:48:37 +0300
Subject: [PATCH 090/101] Update myisam_debug test result post print_lock_error
change
---
mysql-test/r/myisam_debug.result | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mysql-test/r/myisam_debug.result b/mysql-test/r/myisam_debug.result
index 77de991bafd..ca45ce1fc9f 100644
--- a/mysql-test/r/myisam_debug.result
+++ b/mysql-test/r/myisam_debug.result
@@ -36,6 +36,6 @@ set debug_dbug='+d,mi_lock_database_failure';
unlock tables;
Warnings:
Error 126 Incorrect key file for table './test/t1.MYI'; try to repair it
-Error 1015 Can't lock file (errno: 22 "Invalid argument")
+Error 1030 Got error 22 "Invalid argument" from storage engine MyISAM
set debug_dbug=@old_dbug;
drop table t1;
From 31f4df450502d96854c052ce3cd2858ce9dbf900 Mon Sep 17 00:00:00 2001
From: Elena Stepanova
Date: Mon, 31 Jul 2017 20:34:22 +0300
Subject: [PATCH 091/101] MDEV-12915 ST_Centroid does not return the same
result than MySQL
Fix storage_engine test results
---
mysql-test/suite/storage_engine/type_spatial.result | 4 ++--
.../suite/storage_engine/type_spatial_indexes.result | 8 ++++----
.../mysql-test/storage_engine/type_spatial_indexes.rdiff | 4 ++--
.../mysql-test/storage_engine/type_spatial.rdiff | 4 ++--
.../mysql-test/storage_engine/type_spatial_indexes.rdiff | 8 ++++----
.../mysql-test/storage_engine/type_spatial_indexes.rdiff | 4 ++--
6 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/mysql-test/suite/storage_engine/type_spatial.result b/mysql-test/suite/storage_engine/type_spatial.result
index 6c2f5a4d50f..71211bd2057 100644
--- a/mysql-test/suite/storage_engine/type_spatial.result
+++ b/mysql-test/suite/storage_engine/type_spatial.result
@@ -350,8 +350,8 @@ fid IsClosed(g)
116 0
SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
fid AsText(Centroid(g))
-117 POINT(55.58852775304245 17.426536064113982)
-118 POINT(55.58852775304245 17.426536064113982)
+117 POINT(57.98031067576927 17.854754130800433)
+118 POINT(57.98031067576927 17.854754130800433)
119 POINT(2 2)
SELECT fid, Area(g) FROM gis_multi_polygon;
fid Area(g)
diff --git a/mysql-test/suite/storage_engine/type_spatial_indexes.result b/mysql-test/suite/storage_engine/type_spatial_indexes.result
index 93bb4c617e5..b2e00463606 100644
--- a/mysql-test/suite/storage_engine/type_spatial_indexes.result
+++ b/mysql-test/suite/storage_engine/type_spatial_indexes.result
@@ -350,8 +350,8 @@ fid IsClosed(g)
116 0
SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
fid AsText(Centroid(g))
-117 POINT(55.58852775304245 17.426536064113982)
-118 POINT(55.58852775304245 17.426536064113982)
+117 POINT(57.98031067576927 17.854754130800433)
+118 POINT(57.98031067576927 17.854754130800433)
119 POINT(2 2)
SELECT fid, Area(g) FROM gis_multi_polygon;
fid Area(g)
@@ -1050,8 +1050,8 @@ fid IsClosed(g)
116 0
SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
fid AsText(Centroid(g))
-117 POINT(55.58852775304245 17.426536064113982)
-118 POINT(55.58852775304245 17.426536064113982)
+117 POINT(57.98031067576927 17.854754130800433)
+118 POINT(57.98031067576927 17.854754130800433)
119 POINT(2 2)
SELECT fid, Area(g) FROM gis_multi_polygon;
fid Area(g)
diff --git a/storage/innobase/mysql-test/storage_engine/type_spatial_indexes.rdiff b/storage/innobase/mysql-test/storage_engine/type_spatial_indexes.rdiff
index d3fb59e6ce3..111fb0033bd 100644
--- a/storage/innobase/mysql-test/storage_engine/type_spatial_indexes.rdiff
+++ b/storage/innobase/mysql-test/storage_engine/type_spatial_indexes.rdiff
@@ -352,8 +352,8 @@
-116 0
-SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
-fid AsText(Centroid(g))
--117 POINT(55.58852775304245 17.426536064113982)
--118 POINT(55.58852775304245 17.426536064113982)
+-117 POINT(57.98031067576927 17.854754130800433)
+-118 POINT(57.98031067576927 17.854754130800433)
-119 POINT(2 2)
-SELECT fid, Area(g) FROM gis_multi_polygon;
-fid Area(g)
diff --git a/storage/myisammrg/mysql-test/storage_engine/type_spatial.rdiff b/storage/myisammrg/mysql-test/storage_engine/type_spatial.rdiff
index 52e9d9fdbe4..70675d241b9 100644
--- a/storage/myisammrg/mysql-test/storage_engine/type_spatial.rdiff
+++ b/storage/myisammrg/mysql-test/storage_engine/type_spatial.rdiff
@@ -352,8 +352,8 @@
-116 0
-SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
-fid AsText(Centroid(g))
--117 POINT(55.58852775304245 17.426536064113982)
--118 POINT(55.58852775304245 17.426536064113982)
+-117 POINT(57.98031067576927 17.854754130800433)
+-118 POINT(57.98031067576927 17.854754130800433)
-119 POINT(2 2)
-SELECT fid, Area(g) FROM gis_multi_polygon;
-fid Area(g)
diff --git a/storage/myisammrg/mysql-test/storage_engine/type_spatial_indexes.rdiff b/storage/myisammrg/mysql-test/storage_engine/type_spatial_indexes.rdiff
index ecd0025c9d9..b14bd251f58 100644
--- a/storage/myisammrg/mysql-test/storage_engine/type_spatial_indexes.rdiff
+++ b/storage/myisammrg/mysql-test/storage_engine/type_spatial_indexes.rdiff
@@ -352,8 +352,8 @@
-116 0
-SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
-fid AsText(Centroid(g))
--117 POINT(55.58852775304245 17.426536064113982)
--118 POINT(55.58852775304245 17.426536064113982)
+-117 POINT(57.98031067576927 17.854754130800433)
+-118 POINT(57.98031067576927 17.854754130800433)
-119 POINT(2 2)
-SELECT fid, Area(g) FROM gis_multi_polygon;
-fid Area(g)
@@ -1062,8 +1062,8 @@
-116 0
-SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
-fid AsText(Centroid(g))
--117 POINT(55.58852775304245 17.426536064113982)
--118 POINT(55.58852775304245 17.426536064113982)
+-117 POINT(57.98031067576927 17.854754130800433)
+-118 POINT(57.98031067576927 17.854754130800433)
-119 POINT(2 2)
-SELECT fid, Area(g) FROM gis_multi_polygon;
-fid Area(g)
diff --git a/storage/xtradb/mysql-test/storage_engine/type_spatial_indexes.rdiff b/storage/xtradb/mysql-test/storage_engine/type_spatial_indexes.rdiff
index d3fb59e6ce3..111fb0033bd 100644
--- a/storage/xtradb/mysql-test/storage_engine/type_spatial_indexes.rdiff
+++ b/storage/xtradb/mysql-test/storage_engine/type_spatial_indexes.rdiff
@@ -352,8 +352,8 @@
-116 0
-SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
-fid AsText(Centroid(g))
--117 POINT(55.58852775304245 17.426536064113982)
--118 POINT(55.58852775304245 17.426536064113982)
+-117 POINT(57.98031067576927 17.854754130800433)
+-118 POINT(57.98031067576927 17.854754130800433)
-119 POINT(2 2)
-SELECT fid, Area(g) FROM gis_multi_polygon;
-fid Area(g)
From 60c9485a8e5ebf410d9fa60caa7937f3fe3ca9b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Tue, 1 Aug 2017 11:39:10 +0300
Subject: [PATCH 092/101] Merge connect/10.0 into 10.0
Squash all connect/10.0's commits into one and keep only
changes from storage/connect directory.
---
storage/connect/array.cpp | 12 +-
storage/connect/blkfil.cpp | 10 +-
storage/connect/colblk.cpp | 10 +-
storage/connect/connect.cc | 11 +-
storage/connect/connect.h | 3 +-
storage/connect/engmsg.h | 1 +
storage/connect/filter.cpp | 14 +-
storage/connect/global.h | 4 +-
storage/connect/ha_connect.cc | 162 +++++++++++------
storage/connect/ha_connect.h | 3 +-
storage/connect/jdbconn.cpp | 143 ++++++++-------
storage/connect/json.cpp | 139 +++++++++++++--
storage/connect/json.h | 36 ++--
storage/connect/jsonudf.cpp | 61 ++++---
storage/connect/msgid.h | 1 +
storage/connect/mycat.cc | 2 +-
storage/connect/mycat.h | 4 +-
.../connect/r/drop-open-error.result | 14 ++
.../mysql-test/connect/r/grant2.result | 3 +-
.../connect/r/infoschema-9739.result | 12 ++
.../mysql-test/connect/r/json_udf.result | 2 +-
.../mysql-test/connect/r/mysql_new.result | 2 +-
.../mysql-test/connect/r/odbc_firebird.result | 165 ++++++++++++++++++
.../mysql-test/connect/std_data/mdev9949.frm | Bin 0 -> 35031 bytes
.../mysql-test/connect/t/drop-open-error.opt | 1 +
.../mysql-test/connect/t/drop-open-error.test | 31 ++++
.../connect/mysql-test/connect/t/grant2.test | 1 +
.../mysql-test/connect/t/infoschema-9739.test | 9 +
.../mysql-test/connect/t/mysql_new.test | 2 +-
.../mysql-test/connect/t/odbc_firebird.test | 35 ++++
.../connect/t/secure_file_priv.test | 2 +-
storage/connect/noconst.c | 38 ++++
storage/connect/os.h | 1 +
storage/connect/osutil.c | 1 +
storage/connect/osutil.h | 1 +
storage/connect/plgdbsem.h | 2 -
storage/connect/plgdbutl.cpp | 22 +--
storage/connect/plugutil.cpp | 98 ++++++-----
storage/connect/tabcol.cpp | 8 +-
storage/connect/tabdos.cpp | 152 ++++++++--------
storage/connect/tabjson.cpp | 32 ++--
storage/connect/table.cpp | 2 +-
storage/connect/tabodbc.cpp | 4 +-
storage/connect/tabodbc.h | 2 +-
storage/connect/tabvir.cpp | 2 +-
storage/connect/tabxml.cpp | 40 ++---
storage/connect/user_connect.cc | 37 ++--
storage/connect/user_connect.h | 5 +-
storage/connect/value.cpp | 71 ++++----
storage/connect/value.h | 4 +-
storage/connect/xindex.cpp | 20 ++-
storage/connect/xobject.cpp | 10 +-
52 files changed, 983 insertions(+), 464 deletions(-)
create mode 100644 storage/connect/mysql-test/connect/r/drop-open-error.result
create mode 100644 storage/connect/mysql-test/connect/r/infoschema-9739.result
create mode 100644 storage/connect/mysql-test/connect/r/odbc_firebird.result
create mode 100644 storage/connect/mysql-test/connect/std_data/mdev9949.frm
create mode 100644 storage/connect/mysql-test/connect/t/drop-open-error.opt
create mode 100644 storage/connect/mysql-test/connect/t/drop-open-error.test
create mode 100644 storage/connect/mysql-test/connect/t/infoschema-9739.test
create mode 100644 storage/connect/mysql-test/connect/t/odbc_firebird.test
create mode 100644 storage/connect/noconst.c
diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp
index 6e0da312ca3..4868925f3c2 100644
--- a/storage/connect/array.cpp
+++ b/storage/connect/array.cpp
@@ -520,7 +520,7 @@ bool ARRAY::FilTest(PGLOBAL g, PVAL valp, OPVAL opc, int opm)
} else if (opc != OP_EXIST) {
sprintf(g->Message, MSG(MISSING_ARG), opc);
- throw TYPE_ARRAY;
+ throw (int)TYPE_ARRAY;
} else // OP_EXIST
return Nval > 0;
@@ -683,14 +683,14 @@ void ARRAY::SetPrecision(PGLOBAL g, int p)
{
if (Vblp == NULL) {
strcpy(g->Message, MSG(PREC_VBLP_NULL));
- throw TYPE_ARRAY;
+ throw (int)TYPE_ARRAY;
} // endif Vblp
bool was = Vblp->IsCi();
if (was && !p) {
strcpy(g->Message, MSG(BAD_SET_CASE));
- throw TYPE_ARRAY;
+ throw (int)TYPE_ARRAY;
} // endif Vblp
if (was || !p)
@@ -701,7 +701,7 @@ void ARRAY::SetPrecision(PGLOBAL g, int p)
if (!was && Type == TYPE_STRING)
// Must be resorted to eliminate duplicate strings
if (Sort(g))
- throw TYPE_ARRAY;
+ throw (int)TYPE_ARRAY;
} // end of SetPrecision
@@ -1035,7 +1035,7 @@ void ARRAY::Printf(PGLOBAL g, FILE *f, uint n)
} else
fprintf(f, "%sVALLST: numval=%d\n", m, Nval);
- } // end of Print
+ } // end of Printf
/***********************************************************************/
/* Make string output of ARRAY contents. */
@@ -1047,7 +1047,7 @@ void ARRAY::Prints(PGLOBAL, char *ps, uint z)
sprintf(ps, "ARRAY: type=%d\n", Type);
// More to be implemented later
- } // end of Print
+ } // end of Prints
/* -------------------------- Class MULAR ---------------------------- */
diff --git a/storage/connect/blkfil.cpp b/storage/connect/blkfil.cpp
index 77a46260934..802095f2f82 100644
--- a/storage/connect/blkfil.cpp
+++ b/storage/connect/blkfil.cpp
@@ -65,7 +65,7 @@ void BLOCKFILTER::Printf(PGLOBAL, FILE *f, uint n)
fprintf(f, "%sBLOCKFILTER: at %p opc=%d opm=%d result=%d\n",
m, this, Opc, Opm, Result);
- } // end of Print
+ } // end of Printf
/***********************************************************************/
/* Make string output of BLOCKFILTER contents. */
@@ -73,7 +73,7 @@ void BLOCKFILTER::Printf(PGLOBAL, FILE *f, uint n)
void BLOCKFILTER::Prints(PGLOBAL, char *ps, uint z)
{
strncat(ps, "BlockFilter(s)", z);
- } // end of Print
+ } // end of Prints
/* ---------------------- Class BLKFILLOG ---------------------------- */
@@ -1006,9 +1006,9 @@ void BLOCKINDEX::Printf(PGLOBAL g, FILE *f, UINT n)
m, this, Next, (Colp) ? Colp->GetName() : "Rowid", Kxp, Result);
if (Next)
- Next->Print(g, f, n);
+ Next->Printf(g, f, n);
- } // end of Print
+ } // end of Printf
/***********************************************************************/
/* Make string output of BLOCKINDEX contents. */
@@ -1016,7 +1016,7 @@ void BLOCKINDEX::Printf(PGLOBAL g, FILE *f, UINT n)
void BLOCKINDEX::Prints(PGLOBAL g, char *ps, UINT z)
{
strncat(ps, "BlockIndex(es)", z);
- } // end of Print
+ } // end of Prints
/* ------------------------------------------------------------------- */
diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp
index 324d59ab40e..2ffe51d2009 100644
--- a/storage/connect/colblk.cpp
+++ b/storage/connect/colblk.cpp
@@ -197,7 +197,7 @@ int COLBLK::GetLengthEx(void)
void COLBLK::ReadColumn(PGLOBAL g)
{
sprintf(g->Message, MSG(UNDEFINED_AM), "ReadColumn");
- throw TYPE_COLBLK;
+ throw (int)TYPE_COLBLK;
} // end of ReadColumn
/***********************************************************************/
@@ -208,7 +208,7 @@ void COLBLK::ReadColumn(PGLOBAL g)
void COLBLK::WriteColumn(PGLOBAL g)
{
sprintf(g->Message, MSG(UNDEFINED_AM), "WriteColumn");
- throw TYPE_COLBLK;
+ throw (int)TYPE_COLBLK;
} // end of WriteColumn
/***********************************************************************/
@@ -232,7 +232,7 @@ void COLBLK::Printf(PGLOBAL, FILE *f, uint n)
fprintf(f,
" coluse=%04X status=%04X buftyp=%d value=%p name=%s\n",
ColUse, Status, Buf_Type, Value, Name);
- } // end of Print
+ } // end of Printf
/***********************************************************************/
/* Make string output of a column descriptor block. */
@@ -240,7 +240,7 @@ void COLBLK::Printf(PGLOBAL, FILE *f, uint n)
void COLBLK::Prints(PGLOBAL, char *ps, uint)
{
sprintf(ps, "R%d.%s", To_Tdb->GetTdb_No(), Name);
- } // end of Print
+ } // end of Prints
/***********************************************************************/
@@ -262,7 +262,7 @@ SPCBLK::SPCBLK(PCOLUMN cp)
void SPCBLK::WriteColumn(PGLOBAL g)
{
sprintf(g->Message, MSG(SPCOL_READONLY), Name);
- throw TYPE_COLBLK;
+ throw (int)TYPE_COLBLK;
} // end of WriteColumn
/***********************************************************************/
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index e15cc724b85..c5a29fe7416 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -1,4 +1,5 @@
/* Copyright (C) Olivier Bertrand 2004 - 2017
+ Copyright (C) MariaDB Corporation Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -66,8 +67,10 @@ PGLOBAL CntExit(PGLOBAL g)
if (g) {
CntEndDB(g);
- if (g->Activityp)
- delete g->Activityp;
+ if (g->Activityp) {
+ delete g->Activityp;
+ g->Activityp = NULL;
+ } // endif Activityp
PlugExit(g);
g= NULL;
@@ -185,10 +188,10 @@ bool CntInfo(PGLOBAL g, PTDB tp, PXF info)
/***********************************************************************/
PTDB CntGetTDB(PGLOBAL g, LPCSTR name, MODE mode, PHC h)
{
- PTDB tdbp;
+ PTDB tdbp = NULL;
PTABLE tabp;
PDBUSER dup = PlgGetUser(g);
- volatile PCATLG cat = (dup) ? dup->Catalog : NULL; // Safe over longjmp
+ volatile PCATLG cat = (dup) ? dup->Catalog : NULL; // Safe over throw
if (trace)
printf("CntGetTDB: name=%s mode=%d cat=%p\n", name, mode, cat);
diff --git a/storage/connect/connect.h b/storage/connect/connect.h
index 128561b80f3..2bca8bf54cb 100644
--- a/storage/connect/connect.h
+++ b/storage/connect/connect.h
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2011
+/* Copyright (C) MariaDB Corporation Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,6 +15,7 @@
/**************** Cnt H Declares Source Code File (.H) *****************/
/* Name: CONNECT.H Version 2.4 */
+/* Author Olivier BERTRAND bertrandop@gmail.com */
/* This file contains the some based classes declares. */
/***********************************************************************/
#include "filamtxt.h"
diff --git a/storage/connect/engmsg.h b/storage/connect/engmsg.h
index 14808758efd..c072511065e 100644
--- a/storage/connect/engmsg.h
+++ b/storage/connect/engmsg.h
@@ -1,3 +1,4 @@
+/* Copyright (C) MariaDB Corporation Ab */
#define MSG_ACCESS_VIOLATN "Access violation"
#define MSG_ADD_BAD_TYPE "Array add value type mismatch (%s -> %s)"
#define MSG_ALLOC_ERROR "Error allocating %s"
diff --git a/storage/connect/filter.cpp b/storage/connect/filter.cpp
index da44b129ccb..d592dc27cf3 100644
--- a/storage/connect/filter.cpp
+++ b/storage/connect/filter.cpp
@@ -87,7 +87,7 @@ BYTE OpBmp(PGLOBAL g, OPVAL opc)
case OP_EXIST: bt = 0x00; break;
default:
sprintf(g->Message, MSG(BAD_FILTER_OP), opc);
- throw TYPE_ARRAY;
+ throw (int)TYPE_FILTER;
} // endswitch opc
return bt;
@@ -1437,7 +1437,7 @@ void FILTER::Printf(PGLOBAL g, FILE *f, uint n)
} // endfor fp
- } // end of Print
+ } // end of Printf
/***********************************************************************/
/* Make string output of TABLE contents (z should be checked). */
@@ -1579,7 +1579,7 @@ void FILTER::Prints(PGLOBAL g, char *ps, uint z)
bcp = bxp;
} while (bcp); // enddo
- } // end of Print
+ } // end of Prints
/* -------------------- Derived Classes Functions -------------------- */
@@ -1697,8 +1697,6 @@ PFIL PrepareFilter(PGLOBAL g, PFIL fp, bool having)
if (trace)
htrc("PrepareFilter: fp=%p having=%d\n", fp, having);
-//if (fp)
-// fp->Print(g, debug, 0);
while (fp) {
if (fp->Opc == OP_SEP)
@@ -1712,7 +1710,7 @@ PFIL PrepareFilter(PGLOBAL g, PFIL fp, bool having)
break; // Remove eventual ending separator(s)
// if (fp->Convert(g, having))
-// throw TYPE_ARRAY;
+// throw (int)TYPE_FILTER;
filp = fp;
fp = fp->Next;
@@ -1721,8 +1719,6 @@ PFIL PrepareFilter(PGLOBAL g, PFIL fp, bool having)
if (trace)
htrc(" returning filp=%p\n", filp);
-//if (filp)
-// filp->Print(g, debug, 0);
return filp;
} // end of PrepareFilter
@@ -1745,7 +1741,7 @@ DllExport bool ApplyFilter(PGLOBAL g, PFIL filp)
// return TRUE;
if (filp->Eval(g))
- throw TYPE_FILTER;
+ throw (int)TYPE_FILTER;
if (trace > 1)
htrc("PlugFilter filp=%p result=%d\n",
diff --git a/storage/connect/global.h b/storage/connect/global.h
index a2030fdb5d0..cb756494efc 100644
--- a/storage/connect/global.h
+++ b/storage/connect/global.h
@@ -1,6 +1,7 @@
/***********************************************************************/
/* GLOBAL.H: Declaration file used by all CONNECT implementations. */
-/* (C) Copyright Olivier Bertrand 1993-2017 */
+/* (C) Copyright MariaDB Corporation Ab */
+/* Author Olivier Bertrand 1993-2017 */
/***********************************************************************/
/***********************************************************************/
@@ -90,6 +91,7 @@
#define TYPE_BIGINT 5
#define TYPE_LIST 6
#define TYPE_INT 7
+#define TYPE_DATE 8
#define TYPE_DECIM 9
#define TYPE_BIN 10
#define TYPE_PCHAR 11
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 89dc1502656..d6e37700e4f 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2017
+/* Copyright (C) MariaDB Corporation Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -98,9 +98,8 @@
rnd_next signals that it has reached the end of its data. Calls to
ha_connect::extra() are hints as to what will be occuring to the request.
- Happy use!
- -Olivier
-*/
+ Author Olivier Bertrand
+ */
#ifdef USE_PRAGMA_IMPLEMENTATION
#pragma implementation // gcc: Class implementation
@@ -198,11 +197,13 @@ extern "C" {
char *ClassPath;
#endif // JDBC_SUPPORT
-#if defined(__WIN__)
-CRITICAL_SECTION parsec; // Used calling the Flex parser
-#else // !__WIN__
-pthread_mutex_t parmut = PTHREAD_MUTEX_INITIALIZER;
-#endif // !__WIN__
+//#if defined(__WIN__)
+//CRITICAL_SECTION parsec; // Used calling the Flex parser
+//#else // !__WIN__
+//pthread_mutex_t parmut = PTHREAD_MUTEX_INITIALIZER;
+//#endif // !__WIN__
+pthread_mutex_t parmut;
+pthread_mutex_t usrmut;
/***********************************************************************/
/* Utility functions. */
@@ -221,6 +222,7 @@ void mongo_init(bool);
USETEMP UseTemp(void);
int GetConvSize(void);
TYPCONV GetTypeConv(void);
+char *GetJsonNull(void);
uint GetJsonGrpSize(void);
char *GetJavaWrapper(void);
uint GetWorkSize(void);
@@ -330,6 +332,13 @@ static MYSQL_THDVAR_ENUM(
0, // def (no)
&xconv_typelib); // typelib
+// Null representation for JSON values
+static MYSQL_THDVAR_STR(json_null,
+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
+ "Representation of Json null values",
+ // check_json_null, update_json_null,
+ NULL, NULL, "");
+
// Estimate max number of rows for JSON aggregate functions
static MYSQL_THDVAR_UINT(json_grp_size,
PLUGIN_VAR_RQCMDARG, // opt
@@ -381,6 +390,8 @@ bool ExactInfo(void) {return THDVAR(current_thd, exact_info);}
USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);}
int GetConvSize(void) {return THDVAR(current_thd, conv_size);}
TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);}
+char *GetJsonNull(void)
+ {return connect_hton ? THDVAR(current_thd, json_null) : NULL;}
uint GetJsonGrpSize(void)
{return connect_hton ? THDVAR(current_thd, json_grp_size) : 10;}
uint GetWorkSize(void) {return THDVAR(current_thd, work_size);}
@@ -666,10 +677,12 @@ static int connect_init_func(void *p)
#if defined(__WIN__)
sql_print_information("CONNECT: %s", compver);
- InitializeCriticalSection((LPCRITICAL_SECTION)&parsec);
+//InitializeCriticalSection((LPCRITICAL_SECTION)&parsec);
#else // !__WIN__
sql_print_information("CONNECT: %s", version);
#endif // !__WIN__
+ pthread_mutex_init(&parmut, NULL);
+ pthread_mutex_init(&usrmut, NULL);
#if defined(LIBXML2_SUPPORT)
XmlInitParserLib();
@@ -718,12 +731,13 @@ static int connect_done_func(void *)
#endif // JDBC_SUPPORT
#if defined(__WIN__)
- DeleteCriticalSection((LPCRITICAL_SECTION)&parsec);
+//DeleteCriticalSection((LPCRITICAL_SECTION)&parsec);
#else // !__WIN__
PROFILE_End();
#endif // !__WIN__
- for (pc= user_connect::to_users; pc; pc= pn) {
+ pthread_mutex_lock(&usrmut);
+ for (pc= user_connect::to_users; pc; pc= pn) {
if (pc->g)
PlugCleanup(pc->g, true);
@@ -731,6 +745,10 @@ static int connect_done_func(void *)
delete pc;
} // endfor pc
+ pthread_mutex_unlock(&usrmut);
+
+ pthread_mutex_destroy(&usrmut);
+ pthread_mutex_destroy(&parmut);
connect_hton= NULL;
DBUG_RETURN(error);
} // end of connect_done_func
@@ -843,6 +861,7 @@ ha_connect::~ha_connect(void)
static void PopUser(PCONNECT xp)
{
if (xp) {
+ pthread_mutex_lock(&usrmut);
xp->count--;
if (!xp->count) {
@@ -867,6 +886,7 @@ static void PopUser(PCONNECT xp)
delete xp;
} // endif count
+ pthread_mutex_unlock(&usrmut);
} // endif xp
} // end of PopUser
@@ -880,23 +900,33 @@ static PCONNECT GetUser(THD *thd, PCONNECT xp)
if (!thd)
return NULL;
- if (xp && thd == xp->thdp)
- return xp;
+ if (xp) {
+ if (thd == xp->thdp)
+ return xp;
- for (xp= user_connect::to_users; xp; xp= xp->next)
+ PopUser(xp); // Avoid memory leak
+ } // endif xp
+
+ pthread_mutex_lock(&usrmut);
+
+ for (xp= user_connect::to_users; xp; xp= xp->next)
if (thd == xp->thdp)
break;
- if (!xp) {
+ if (xp)
+ xp->count++;
+
+ pthread_mutex_unlock(&usrmut);
+
+ if (!xp) {
xp= new user_connect(thd);
if (xp->user_init()) {
delete xp;
xp= NULL;
- } // endif user_init
+ } // endif user_init
- } else
- xp->count++;
+ } // endif xp
return xp;
} // end of GetUser
@@ -1024,37 +1054,55 @@ PCSZ GetListOption(PGLOBAL g, PCSZ opname, PCSZ oplist, PCSZ def)
if (!oplist)
return (char*)def;
- char key[16], val[256];
- char *pk, *pv, *pn;
- PCSZ opval= def;
- int n;
+ char key[16], val[256];
+ char *pv, *pn, *pk = (char*)oplist;
+ PCSZ opval = def;
+ int n;
- for (pk= (char*)oplist; pk; pk= ++pn) {
- pn= strchr(pk, ',');
- pv= strchr(pk, '=');
+ while (*pk == ' ')
+ pk++;
- if (pv && (!pn || pv < pn)) {
- n= MY_MIN(pv - pk, (int)sizeof(key) - 1);
- memcpy(key, pk, n);
- key[n]= 0;
- pv++;
- n= MY_MIN((pn ? pn - pv : strlen(pv)), sizeof(val) - 1);
- memcpy(val, pv, n);
- val[n]= 0;
- } else {
- n= MY_MIN((pn ? pn - pk : strlen(pk)), sizeof(key) - 1);
- memcpy(key, pk, n);
- key[n]= 0;
- val[0]= 0;
- } // endif pv
+ for (; pk; pk = pn) {
+ pn = strchr(pk, ',');
+ pv = strchr(pk, '=');
- if (!stricmp(opname, key)) {
- opval= PlugDup(g, val);
- break;
- } else if (!pn)
- break;
+ if (pv && (!pn || pv < pn)) {
+ n = MY_MIN(static_cast(pv - pk), sizeof(key) - 1);
+ memcpy(key, pk, n);
- } // endfor pk
+ while (n && key[n - 1] == ' ')
+ n--;
+
+ key[n] = 0;
+
+ while (*(++pv) == ' ');
+
+ n = MY_MIN((pn ? pn - pv : strlen(pv)), sizeof(val) - 1);
+ memcpy(val, pv, n);
+
+ while (n && val[n - 1] == ' ')
+ n--;
+
+ val[n] = 0;
+ } else {
+ n = MY_MIN((pn ? pn - pk : strlen(pk)), sizeof(key) - 1);
+ memcpy(key, pk, n);
+
+ while (n && key[n - 1] == ' ')
+ n--;
+
+ key[n] = 0;
+ val[0] = 0;
+ } // endif pv
+
+ if (!stricmp(opname, key)) {
+ opval = PlugDup(g, val);
+ break;
+ } else if (!pn)
+ break;
+
+ while (*(++pn) == ' ');
+ } // endfor pk
return opval;
} // end of GetListOption
@@ -1427,7 +1475,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
pcf->Flags |= U_VAR;
- /* fall through */
+ // fall through
default:
pcf->Type= MYSQLtoPLG(fp->type(), &v);
break;
@@ -2802,7 +2850,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
case Item_func::LIKE_FUNC: vop= OP_LIKE; break;
case Item_func::ISNOTNULL_FUNC:
neg = true;
- /* fall through */
+ // fall through
case Item_func::ISNULL_FUNC: vop= OP_NULL; break;
case Item_func::IN_FUNC: vop= OP_IN;
case Item_func::BETWEEN:
@@ -4052,7 +4100,12 @@ int ha_connect::info(uint flag)
DBUG_ENTER("ha_connect::info");
- if (trace)
+ if (!g) {
+ my_message(ER_UNKNOWN_ERROR, "Cannot get g pointer", MYF(0));
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+ } // endif g
+
+ if (trace)
htrc("%p In info: flag=%u valid_info=%d\n", this, flag, valid_info);
// tdbp must be available to get updated info
@@ -4063,7 +4116,7 @@ int ha_connect::info(uint flag)
if (xmod == MODE_ANY || xmod == MODE_ALTER) {
// Pure info, not a query
pure= true;
- xp->CheckCleanup();
+ xp->CheckCleanup(xmod == MODE_ANY && valid_query_id == 0);
} // endif xmod
// This is necessary for getting file length
@@ -4247,8 +4300,8 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
} else
return false;
- /* check FILE_ACL */
- /* fall through */
+ // check FILE_ACL
+ // fall through
case TAB_ODBC:
case TAB_JDBC:
case TAB_MYSQL:
@@ -7060,7 +7113,8 @@ static struct st_mysql_sys_var* connect_system_variables[]= {
#if defined(XMSG)
MYSQL_SYSVAR(errmsg_dir_path),
#endif // XMSG
- MYSQL_SYSVAR(json_grp_size),
+ MYSQL_SYSVAR(json_null),
+ MYSQL_SYSVAR(json_grp_size),
#if defined(JDBC_SUPPORT)
MYSQL_SYSVAR(jvm_path),
MYSQL_SYSVAR(class_path),
@@ -7083,6 +7137,6 @@ maria_declare_plugin(connect)
NULL, /* status variables */
connect_system_variables, /* system variables */
"1.06.0001", /* string version */
- MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
}
maria_declare_plugin_end;
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 8d8307b4bd1..9d71aaa5433 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2015
+/* Copyright (C) MariaDB Corporation Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,6 +14,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
/** @file ha_connect.h
+ Author Olivier Bertrand
@brief
The ha_connect engine is a prototype storage engine to access external data.
diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp
index f162a7ae645..811f998b55f 100644
--- a/storage/connect/jdbconn.cpp
+++ b/storage/connect/jdbconn.cpp
@@ -120,66 +120,81 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
int type;
switch (stp) {
- case -1: // LONGVARCHAR
- if (GetTypeConv() != TPC_YES)
- return TYPE_ERROR;
- else
- len = MY_MIN(abs(len), GetConvSize());
- case 12: // VARCHAR
- v = 'V';
- case 1: // CHAR
- type = TYPE_STRING;
- break;
- case 2: // NUMERIC
- case 3: // DECIMAL
- case -3: // VARBINARY
- type = TYPE_DECIM;
- break;
- case 4: // INTEGER
- type = TYPE_INT;
- break;
- case 5: // SMALLINT
- type = TYPE_SHORT;
- break;
- case -6: // TINYINT
- case -7: // BIT
- type = TYPE_TINY;
- break;
- case 6: // FLOAT
- case 7: // REAL
- case 8: // DOUBLE
- type = TYPE_DOUBLE;
- break;
- case 93: // TIMESTAMP, DATETIME
- type = TYPE_DATE;
- len = 19 + ((prec) ? (prec+1) : 0);
- v = (tn && toupper(tn[0]) == 'T') ? 'S' : 'E';
- break;
- case 91: // DATE, YEAR
- type = TYPE_DATE;
+ case -1: // LONGVARCHAR
+ case -16: // LONGNVARCHAR (unicode)
+ if (GetTypeConv() != TPC_YES)
+ return TYPE_ERROR;
+ else
+ len = MY_MIN(abs(len), GetConvSize());
+ case 12: // VARCHAR
+ case -9: // NVARCHAR (unicode)
+ v = 'V';
+ case 1: // CHAR
+ case -15: // NCHAR (unicode)
+ case -8: // ROWID
+ type = TYPE_STRING;
+ break;
+ case 2: // NUMERIC
+ case 3: // DECIMAL
+ case -3: // VARBINARY
+ type = TYPE_DECIM;
+ break;
+ case 4: // INTEGER
+ type = TYPE_INT;
+ break;
+ case 5: // SMALLINT
+ type = TYPE_SHORT;
+ break;
+ case -6: // TINYINT
+ case -7: // BIT
+ case 16: // BOOLEAN
+ type = TYPE_TINY;
+ break;
+ case 6: // FLOAT
+ case 7: // REAL
+ case 8: // DOUBLE
+ type = TYPE_DOUBLE;
+ break;
+ case 93: // TIMESTAMP, DATETIME
+ type = TYPE_DATE;
+ len = 19 + ((prec) ? (prec + 1) : 0);
+ v = (tn && toupper(tn[0]) == 'T') ? 'S' : 'E';
+ break;
+ case 91: // DATE, YEAR
+ type = TYPE_DATE;
- if (!tn || toupper(tn[0]) != 'Y') {
- len = 10;
- v = 'D';
- } else {
- len = 4;
- v = 'Y';
- } // endif len
+ if (!tn || toupper(tn[0]) != 'Y') {
+ len = 10;
+ v = 'D';
+ } else {
+ len = 4;
+ v = 'Y';
+ } // endif len
- break;
- case 92: // TIME
- type = TYPE_DATE;
- len = 8 + ((prec) ? (prec+1) : 0);
- v = 'T';
- break;
- case -5: // BIGINT
- type = TYPE_BIGINT;
- break;
- case 0: // NULL
- case -2: // BINARY
- case -4: // LONGVARBINARY
- default:
- type = TYPE_ERROR;
+ break;
+ case 92: // TIME
+ type = TYPE_DATE;
+ len = 8 + ((prec) ? (prec + 1) : 0);
+ v = 'T';
+ break;
+ case -5: // BIGINT
+ type = TYPE_BIGINT;
+ break;
+ case 0: // NULL
+ case -2: // BINARY
+ case -4: // LONGVARBINARY
+ case 70: // DATALINK
+ case 2000: // JAVA_OBJECT
+ case 2001: // DISTINCT
+ case 2002: // STRUCT
+ case 2003: // ARRAY
+ case 2004: // BLOB
+ case 2005: // CLOB
+ case 2006: // REF
+ case 2009: // SQLXML
+ case 2011: // NCLOB
+ default:
+ type = TYPE_ERROR;
len = 0;
} // endswitch type
@@ -1200,7 +1215,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
if (rank == 0)
if (!name || (jn = env->NewStringUTF(name)) == nullptr) {
sprintf(g->Message, "Fail to allocate jstring %s", SVP(name));
- throw TYPE_AM_JDBC;
+ throw (int)TYPE_AM_JDBC;
} // endif name
// Returns 666 is case of error
@@ -1208,7 +1223,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
if (Check((ctyp == 666) ? -1 : 1)) {
sprintf(g->Message, "Getting ctyp: %s", Msg);
- throw TYPE_AM_JDBC;
+ throw (int)TYPE_AM_JDBC;
} // endif Check
if (val->GetNullable())
@@ -1225,9 +1240,12 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
switch (ctyp) {
case 12: // VARCHAR
+ case -9: // NVARCHAR
case -1: // LONGVARCHAR
case 1: // CHAR
- case 3: // DECIMAL
+ case -15: // NCHAR
+ case 3: // DECIMAL
+ case -8: // ROWID
if (jb && ctyp != 3)
cn = (jstring)jb;
else if (!gmID(g, chrfldid, "StringField", "(ILjava/lang/String;)Ljava/lang/String;"))
@@ -1245,6 +1263,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
case 4: // INTEGER
case 5: // SMALLINT
case -6: // TINYINT
+ case 16: // BOOLEAN
case -7: // BIT
if (!gmID(g, intfldid, "IntField", "(ILjava/lang/String;)I"))
val->SetValue((int)env->CallIntMethod(job, intfldid, rank, jn));
@@ -1315,7 +1334,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
env->DeleteLocalRef(jn);
sprintf(g->Message, "SetColumnValue: %s rank=%d ctyp=%d", Msg, rank, (int)ctyp);
- throw TYPE_AM_JDBC;
+ throw (int)TYPE_AM_JDBC;
} // endif Check
if (rank == 0)
diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp
index f8b1caa13e2..da94d4e227c 100644
--- a/storage/connect/json.cpp
+++ b/storage/connect/json.cpp
@@ -1,5 +1,5 @@
/*************** json CPP Declares Source Code File (.H) ***************/
-/* Name: json.cpp Version 1.3 */
+/* Name: json.cpp Version 1.4 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2017 */
/* */
@@ -53,6 +53,38 @@ void trans_func(unsigned int u, _EXCEPTION_POINTERS* pExp)
char *GetExceptionDesc(PGLOBAL g, unsigned int e);
#endif // SE_CATCH
+char *GetJsonNull(void);
+
+/***********************************************************************/
+/* IsNum: check whether this string is all digits. */
+/***********************************************************************/
+bool IsNum(PSZ s)
+{
+ for (char *p = s; *p; p++)
+ if (*p == ']')
+ break;
+ else if (!isdigit(*p) || *p == '-')
+ return false;
+
+ return true;
+} // end of IsNum
+
+/***********************************************************************/
+/* NextChr: return the first found '[' or Sep pointer. */
+/***********************************************************************/
+char *NextChr(PSZ s, char sep)
+{
+ char *p1 = strchr(s, '[');
+ char *p2 = strchr(s, sep);
+
+ if (!p2)
+ return p1;
+ else if (p1)
+ return MY_MIN(p1, p2);
+
+ return p2;
+} // end of NextChr
+
/***********************************************************************/
/* Parse a json string. */
@@ -933,6 +965,25 @@ return false;
/* -------------------------- Class JOBJECT -------------------------- */
+/***********************************************************************/
+/* Return the number of pairs in this object. */
+/***********************************************************************/
+int JOBJECT::GetSize(bool b)
+{
+ if (b) {
+ // Return only non null pairs
+ int n = 0;
+
+ for (PJPR jpp = First; jpp; jpp = jpp->Next)
+ if (jpp->Val && !jpp->Val->IsNull())
+ n++;
+
+ return n;
+ } else
+ return Size;
+
+} // end of GetSize
+
/***********************************************************************/
/* Add a new pair to an Object. */
/***********************************************************************/
@@ -992,14 +1043,31 @@ PSZ JOBJECT::GetText(PGLOBAL g, PSZ text)
if (!First && n)
return NULL;
- else for (PJPR jp = First; jp; jp = jp->Next)
+ else if (n == 1 && Size == 1 && !strcmp(First->GetKey(), "$date")) {
+ int i;
+
+ First->Val->GetText(g, text);
+ i = (text[1] == '-' ? 2 : 1);
+
+ if (IsNum(text + i)) {
+ // Date is in milliseconds
+ int j = (int)strlen(text);
+
+ if (j >= 4 + i)
+ text[j - 3] = 0; // Change it to seconds
+ else
+ strcpy(text, " 0");
+
+ } // endif text
+
+ } else for (PJPR jp = First; jp; jp = jp->Next)
jp->Val->GetText(g, text);
if (n)
PlugSubAlloc(g, NULL, strlen(text) + 1);
return text + n;
-} // end of GetValue;
+} // end of GetText;
/***********************************************************************/
/* Merge two objects. */
@@ -1040,7 +1108,7 @@ void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PCSZ key)
} // end of SetValue
/***********************************************************************/
-/* Delete a value corresponding to the given key. */
+/* Delete a value corresponding to the given key. */
/***********************************************************************/
void JOBJECT::DeleteKey(PCSZ key)
{
@@ -1070,6 +1138,25 @@ bool JOBJECT::IsNull(void)
/* -------------------------- Class JARRAY --------------------------- */
+/***********************************************************************/
+/* Return the number of values in this object. */
+/***********************************************************************/
+int JARRAY::GetSize(bool b)
+{
+ if (b) {
+ // Return only non null values
+ int n = 0;
+
+ for (PJVAL jvp = First; jvp; jvp = jvp->Next)
+ if (!jvp->IsNull())
+ n++;
+
+ return n;
+ } else
+ return Size;
+
+} // end of GetSize
+
/***********************************************************************/
/* Make the array of values from the values list. */
/***********************************************************************/
@@ -1178,18 +1265,42 @@ bool JARRAY::SetValue(PGLOBAL g, PJVAL jvp, int n)
return false;
} // end of SetValue
+/***********************************************************************/
+/* Return the text corresponding to all values. */
+/***********************************************************************/
+PSZ JARRAY::GetText(PGLOBAL g, PSZ text)
+{
+ int n;
+ PJVAL jp;
+
+ if (!text) {
+ text = (char*)PlugSubAlloc(g, NULL, 0);
+ text[0] = 0;
+ n = 1;
+ } else
+ n = 0;
+
+ for (jp = First; jp; jp = jp->Next)
+ jp->GetText(g, text);
+
+ if (n)
+ PlugSubAlloc(g, NULL, strlen(text) + 1);
+
+ return text + n;
+} // end of GetText;
+
/***********************************************************************/
/* Delete a Value from the Arrays Value list. */
/***********************************************************************/
bool JARRAY::DeleteValue(int n)
{
- PJVAL jvp = GetValue(n);
+ PJVAL jvp = GetValue(n);
- if (jvp) {
- jvp->Del = true;
- return false;
- } else
- return true;
+ if (jvp) {
+ jvp->Del = true;
+ return false;
+ } else
+ return true;
} // end of DeleteValue
@@ -1239,7 +1350,7 @@ JTYP JVALUE::GetValType(void)
else if (Value)
return (JTYP)Value->GetType();
else
- return (JTYP)TYPE_VOID;
+ return TYPE_NULL;
} // end of GetValType
@@ -1303,7 +1414,7 @@ PSZ JVALUE::GetString(void)
/***********************************************************************/
PSZ JVALUE::GetText(PGLOBAL g, PSZ text)
{
- if (Jsp && Jsp->GetType() == TYPE_JOB)
+ if (Jsp)
return Jsp->GetText(g, text);
char buf[32];
@@ -1311,8 +1422,8 @@ PSZ JVALUE::GetText(PGLOBAL g, PSZ text)
if (s)
strcat(strcat(text, " "), s);
- else
- strcat(text, " ???");
+ else if (GetJsonNull())
+ strcat(strcat(text, " "), GetJsonNull());
return text;
} // end of GetText
diff --git a/storage/connect/json.h b/storage/connect/json.h
index 49675ce8559..daed055435b 100644
--- a/storage/connect/json.h
+++ b/storage/connect/json.h
@@ -1,7 +1,7 @@
/**************** json H Declares Source Code File (.H) ****************/
/* Name: json.h Version 1.2 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
+/* (C) Copyright to the author Olivier BERTRAND 2014 - 2017 */
/* */
/* This file contains the JSON classes declares. */
/***********************************************************************/
@@ -13,11 +13,13 @@
#define X
#endif
-enum JTYP {TYPE_STRG = 1,
- TYPE_DBL = 2,
- TYPE_BOOL = 4,
- TYPE_BINT = 5,
- TYPE_INTG = 7,
+enum JTYP {TYPE_NULL = TYPE_VOID,
+ TYPE_STRG = TYPE_STRING,
+ TYPE_DBL = TYPE_DOUBLE,
+ TYPE_BOOL = TYPE_TINY,
+ TYPE_BINT = TYPE_BIGINT,
+ TYPE_DTM = TYPE_DATE,
+ TYPE_INTG = TYPE_INT,
TYPE_JSON = 12,
TYPE_JAR,
TYPE_JOB,
@@ -145,6 +147,7 @@ class JSON : public BLOCK {
JSON(void) {Size = 0;}
int size(void) {return Size;}
+ virtual int GetSize(bool b) {return Size;}
virtual void Clear(void) {Size = 0;}
virtual JTYP GetType(void) {return TYPE_JSON;}
virtual JTYP GetValType(void) {X return TYPE_JSON;}
@@ -192,10 +195,11 @@ class JOBJECT : public JSON {
using JSON::GetValue;
using JSON::SetValue;
- virtual void Clear(void) {First = Last = NULL; Size = 0;}
+ virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JOB;}
virtual PJPR GetFirst(void) {return First;}
- virtual PJPR AddPair(PGLOBAL g, PCSZ key);
+ virtual int GetSize(bool b);
+ virtual PJPR AddPair(PGLOBAL g, PCSZ key);
virtual PJOB GetObject(void) {return this;}
virtual PJVAL GetValue(const char* key);
virtual PJAR GetKeyList(PGLOBAL g);
@@ -221,11 +225,13 @@ class JARRAY : public JSON {
using JSON::GetValue;
using JSON::SetValue;
virtual void Clear(void) {First = Last = NULL; Size = 0;}
- virtual JTYP GetType(void) {return TYPE_JAR;}
+ virtual JTYP GetType(void) {return TYPE_JAR;}
virtual PJAR GetArray(void) {return this;}
- PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL);
+ virtual int GetSize(bool b);
+ PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL);
virtual void InitArray(PGLOBAL g);
virtual PJVAL GetValue(int i);
+ virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual bool Merge(PGLOBAL g, PJSON jsp);
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i);
virtual bool DeleteValue(int n);
@@ -245,20 +251,20 @@ class JARRAY : public JSON {
class JVALUE : public JSON {
friend class JARRAY;
friend class JSNX;
+ friend class JSONCOL;
friend PJVAL ParseValue(PGLOBAL, int&, STRG&, bool*);
friend bool SerializeValue(JOUT *, PJVAL);
public:
- JVALUE(void) : JSON()
- {Jsp = NULL; Value = NULL; Next = NULL; Del = false;}
+ JVALUE(void) : JSON() {Clear();}
JVALUE(PJSON jsp) : JSON()
- {Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
- JVALUE(PGLOBAL g, PVAL valp);
+ {Jsp = jsp; Value = NULL; Next = NULL; Del = false; Size = 1;}
+ JVALUE(PGLOBAL g, PVAL valp);
JVALUE(PGLOBAL g, PCSZ strp);
using JSON::GetValue;
using JSON::SetValue;
virtual void Clear(void)
- {Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;}
+ {Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 1;}
virtual JTYP GetType(void) {return TYPE_JVAL;}
virtual JTYP GetValType(void);
virtual PJOB GetObject(void);
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index 4e00703d9ef..23c2b9785bc 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -1,5 +1,5 @@
/****************** jsonudf C++ Program Source Code File (.CPP) ******************/
-/* PROGRAM NAME: jsonudf Version 1.5 */
+/* PROGRAM NAME: jsonudf Version 1.6 */
/* (C) Copyright to the author Olivier BERTRAND 2015-2017 */
/* This program are the JSON User Defined Functions . */
/*********************************************************************************/
@@ -27,7 +27,8 @@
#endif
#define M 7
-uint GetJsonGrpSize(void);
+char *GetJsonNull(void);
+uint GetJsonGrpSize(void);
static int IsJson(UDF_ARGS *args, uint i);
static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i);
static char *handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
@@ -327,11 +328,13 @@ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
SetJsonValue(g, vp, val->GetArray()->GetValue(0), n);
break;
case TYPE_JOB:
- // if (!vp->IsTypeNum() || !Strict) {
+// if (!vp->IsTypeNum() || !Strict) {
vp->SetValue_psz(val->GetObject()->GetText(g, NULL));
break;
- // } // endif Type
+// } // endif Type
+ case TYPE_NULL:
+ vp->SetNull(true);
default:
vp->Reset();
} // endswitch Type
@@ -459,7 +462,7 @@ PVAL JSNX::ExpandArray(PGLOBAL g, PJAR arp, int n)
/*********************************************************************************/
PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
{
-//int i, ars, nv = 0, nextsame = Tjp->NextSame;
+ //int i, ars, nv = 0, nextsame = Tjp->NextSame;
int i, ars, nv = 0, nextsame = 0;
my_bool err;
OPVAL op = Nodes[n].Op;
@@ -468,15 +471,16 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
JVALUE jval;
vp->Reset();
-//ars = MY_MIN(Tjp->Limit, arp->size());
ars = arp->size();
for (i = 0; i < ars; i++) {
jvrp = arp->GetValue(i);
-// do {
- if (n < Nod - 1 && jvrp->GetJson()) {
-// Tjp->NextSame = nextsame;
+ if (!jvrp->IsNull() || (op == OP_CNC && GetJsonNull())) {
+ if (jvrp->IsNull()) {
+ jvrp->Value = AllocateValue(g, GetJsonNull(), TYPE_STRING);
+ jvp = jvrp;
+ } else if (n < Nod - 1 && jvrp->GetJson()) {
jval.SetValue(GetColumnValue(g, jvrp->GetJson(), n + 1));
jvp = &jval;
} else
@@ -490,25 +494,25 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
if (!MulVal->IsZero()) {
switch (op) {
- case OP_CNC:
- if (Nodes[n].CncVal) {
- val[0] = Nodes[n].CncVal;
- err = vp->Compute(g, val, 1, op);
- } // endif CncVal
+ case OP_CNC:
+ if (Nodes[n].CncVal) {
+ val[0] = Nodes[n].CncVal;
+ err = vp->Compute(g, val, 1, op);
+ } // endif CncVal
- val[0] = MulVal;
- err = vp->Compute(g, val, 1, op);
- break;
- // case OP_NUM:
- case OP_SEP:
- val[0] = Nodes[n].Valp;
- val[1] = MulVal;
- err = vp->Compute(g, val, 2, OP_ADD);
- break;
- default:
- val[0] = Nodes[n].Valp;
- val[1] = MulVal;
- err = vp->Compute(g, val, 2, op);
+ val[0] = MulVal;
+ err = vp->Compute(g, val, 1, op);
+ break;
+ // case OP_NUM:
+ case OP_SEP:
+ val[0] = Nodes[n].Valp;
+ val[1] = MulVal;
+ err = vp->Compute(g, val, 2, OP_ADD);
+ break;
+ default:
+ val[0] = Nodes[n].Valp;
+ val[1] = MulVal;
+ err = vp->Compute(g, val, 2, op);
} // endswitch Op
if (err)
@@ -516,7 +520,7 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
} // endif Zero
-// } while (Tjp->NextSame > nextsame);
+ } // endif jvrp
} // endfor i
@@ -1081,6 +1085,7 @@ inline void JsonMemSave(PGLOBAL g)
/*********************************************************************************/
inline void JsonFreeMem(PGLOBAL g)
{
+ g->Activityp = NULL;
PlugExit(g);
} /* end of JsonFreeMem */
diff --git a/storage/connect/msgid.h b/storage/connect/msgid.h
index 0e9c036dc49..cee78aa1783 100644
--- a/storage/connect/msgid.h
+++ b/storage/connect/msgid.h
@@ -1,3 +1,4 @@
+/* Copyright (C) MariaDB Corporation Ab */
#define MSG_ACCESS_VIOLATN 200
#define MSG_ADD_BAD_TYPE 201
#define MSG_ALLOC_ERROR 202
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc
index 750cf3c0639..c854ba72bff 100644
--- a/storage/connect/mycat.cc
+++ b/storage/connect/mycat.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2017
+/* Copyright (C) MariaDB Corporation Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h
index b6bdd5e5e11..c0f70522b69 100644
--- a/storage/connect/mycat.h
+++ b/storage/connect/mycat.h
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2015
+/* Copyright (C) MariaDB Corporation Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
/**************** MYCAT H Declares Source Code File (.H) ***************/
/* Name: MYCAT.H Version 2.3 */
-/* */
+/* Author: Olivier Bertrand */
/* This file contains the CONNECT plugin MYCAT class definitions. */
/***********************************************************************/
#ifndef __MYCAT__H
diff --git a/storage/connect/mysql-test/connect/r/drop-open-error.result b/storage/connect/mysql-test/connect/r/drop-open-error.result
new file mode 100644
index 00000000000..db699d62421
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/drop-open-error.result
@@ -0,0 +1,14 @@
+create table t1 (c varchar(8));
+create table tcon engine=connect table_type=mysql CONNECTION='mysql://root@localhost/test/t1' SRCDEF='select c from t1 where c in ("foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar")';
+ERROR HY000: Engine CONNECT failed to discover table `test`.`tcon` with 'CREATE TABLE whatever (`c` VARCHAR(8)) TABLE_TYPE='mysql' SRCDEF='select c from t1 where c in ("foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "
+DROP TABLE tcon;
+drop table mdev9949;
+drop table t1;
+select @@secure_file_priv 'must be NULL';
+must be NULL
+NULL
+create table t1 (a char(16)) engine=myisam;
+insert into t1 values('Hello World!');
+create table t2 engine=connect file_name='foo/bar.txt' as select * from t1;
+ERROR HY000: Got error 174 'Open(a+b) error 2 on foo/bar.txt: No such file or directory' from CONNECT
+drop table t1;
diff --git a/storage/connect/mysql-test/connect/r/grant2.result b/storage/connect/mysql-test/connect/r/grant2.result
index f4a78f9b891..0259dd74cdc 100644
--- a/storage/connect/mysql-test/connect/r/grant2.result
+++ b/storage/connect/mysql-test/connect/r/grant2.result
@@ -1,6 +1,7 @@
#
# MDEV-7574 Security definer views don't work with CONNECT ODBC tables
#
+CREATE USER user@localhost;
GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost;
# Testing SQLCOM_SELECT
@@ -621,7 +622,7 @@ test.t1 optimize status OK
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize Error Access denied for user 'user'@'localhost' (using password: NO)
-test.t1 optimize Error Can't lock file (errno: 122 "Internal (unspecified) error in handler")
+test.t1 optimize Error Got error 122 'This operation requires the FILE privilege' from CONNECT
test.t1 optimize error Corrupt
DROP TABLE t1;
# Testing SQLCOM_ALTER_TABLE (adding columns)
diff --git a/storage/connect/mysql-test/connect/r/infoschema-9739.result b/storage/connect/mysql-test/connect/r/infoschema-9739.result
new file mode 100644
index 00000000000..bcebec1d0e0
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/infoschema-9739.result
@@ -0,0 +1,12 @@
+Warnings:
+Warning 1105 No file name. Table will use t1.xml
+create table t1 (i int) engine=Connect table_type=XML;
+Warnings:
+Warning 1105 No file name. Table will use t1.xml
+select * from information_schema.tables where create_options like '%table_type=XML%';
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT
+Warnings:
+Warning 1286 Unknown storage engine 'InnoDB'
+Warning 1286 Unknown storage engine 'InnoDB'
+Warning 1296 Got error 174 'File t1.xml not found' from CONNECT
+drop table t1;
diff --git a/storage/connect/mysql-test/connect/r/json_udf.result b/storage/connect/mysql-test/connect/r/json_udf.result
index 1e83834cb8f..27f4f8b5319 100644
--- a/storage/connect/mysql-test/connect/r/json_udf.result
+++ b/storage/connect/mysql-test/connect/r/json_udf.result
@@ -608,7 +608,7 @@ JsonGet_String(Json_File('test/fx.json'), '[1]:*')
{"_id":6,"type":"car","item":"roadster","mileage":56000,"ratings":[6,9]}
SELECT JsonGet_String(Json_File('test/fx.json'), '[1]');
JsonGet_String(Json_File('test/fx.json'), '[1]')
-6 car roadster 56000 ???
+6 car roadster 56000 6 9
SELECT JsonGet_Int(Json_File('test/fx.json'), '[1]:mileage') AS Mileage;
Mileage
56000
diff --git a/storage/connect/mysql-test/connect/r/mysql_new.result b/storage/connect/mysql-test/connect/r/mysql_new.result
index 327afa34446..309d69abe7e 100644
--- a/storage/connect/mysql-test/connect/r/mysql_new.result
+++ b/storage/connect/mysql-test/connect/r/mysql_new.result
@@ -178,7 +178,7 @@ DROP TABLE t1;
#
# Testing temporal data types
#
-CREATE TABLE t1 (a date, b datetime, c time, d timestamp, e year);
+CREATE TABLE t1 (a date, b datetime, c time, d timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, e year);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
diff --git a/storage/connect/mysql-test/connect/r/odbc_firebird.result b/storage/connect/mysql-test/connect/r/odbc_firebird.result
new file mode 100644
index 00000000000..b0c2582abeb
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/odbc_firebird.result
@@ -0,0 +1,165 @@
+SET NAMES utf8;
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Bad connection string';
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `Name` varchar(256) NOT NULL,
+ `Description` varchar(256) DEFAULT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Sources'
+SELECT * FROM t1;
+Name Description
+dBASE Files Microsoft Access dBASE Driver (*.dbf, *.ndx, *.mdx)
+PLUGDB_DEBUG PLUGODBC_Driver
+PLUGDB_ODBC PLUGODBC_Driver
+SafeDB_ODBC SDB_ODBC_Driver
+Firebird Firebird/InterBase(r) driver
+ConnectEngineXLS Microsoft Excel Driver (*.xls)
+Excel Files Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)
+MariaODBC MySQL ODBC 5.2a Driver
+MariaODBCbeta MariaDB ODBC 1.0 Driver
+MyODBC MySQL ODBC 5.2a Driver
+MS Access Database Microsoft Access Driver (*.mdb, *.accdb)
+MS Access Db1 Microsoft Access Driver (*.mdb)
+MySQL-ANSI MySQL ODBC 5.3 ANSI Driver
+MySQL-Unicode MySQL ODBC 5.3 Unicode Driver
+Xtreme Sample Database 2008 Microsoft Access Driver (*.mdb)
+PlugDB test PLUGODBC_Driver
+SQLite3 Datasource SQLite3 ODBC Driver
+SQLite Datasource SQLite ODBC Driver
+SQLite UTF-8 Datasource SQLite ODBC (UTF-8) Driver
+ORACLE_TEST Oracle in XE
+ConnectEnginePostgresql PostgreSQL ODBC Driver(ANSI)
+ConnectEngineOracle Oracle in XE
+ConnectEngineSQLServer SQL Server
+DROP TABLE t1;
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `Description` char(128) NOT NULL,
+ `Attributes` varchar(256) DEFAULT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers'
+SELECT * FROM t1;
+Description Attributes
+SQL Server UsageCount=1;SQLLevel=1;FileUsage=0;DriverODBCVer=03.50;ConnectFunctions=YYY;APILevel=2;CPTimeout=60;
+Microsoft ODBC for Oracle UsageCount=1;SQLLevel=1;FileUsage=0;DriverODBCVer=02.50;ConnectFunctions=YYY;APILevel=1;CPTimeout=120;
+Microsoft Access Driver (*.mdb) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=2;FileExtns=*.mdb;SQLLevel=0;
+Microsoft Access-Treiber (*.mdb) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=2;FileExtns=*.mdb;SQLLevel=0;
+Driver do Microsoft Access (*.mdb) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=2;FileExtns=*.mdb;SQLLevel=0;
+Microsoft dBase Driver (*.dbf) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.ndx,*.mdx;SQLLevel=0;
+Microsoft dBase-Treiber (*.dbf) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.ndx,*.mdx;SQLLevel=0;
+Driver do Microsoft dBase (*.dbf) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.ndx,*.mdx;SQLLevel=0;
+Microsoft Excel Driver (*.xls) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.xls;SQLLevel=0;
+Microsoft Excel-Treiber (*.xls) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.xls;SQLLevel=0;
+Driver do Microsoft Excel(*.xls) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.xls;SQLLevel=0;
+Microsoft Paradox Driver (*.db ) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.db;SQLLevel=0;
+Microsoft Paradox-Treiber (*.db ) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.db;SQLLevel=0;
+Driver do Microsoft Paradox (*.db ) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.db;SQLLevel=0;
+Microsoft Text Driver (*.txt; *.csv) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.,*.asc,*.csv,*.tab,*.txt,*.csv;SQLLevel=0;
+Microsoft Text-Treiber (*.txt; *.csv) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.,*.asc,*.csv,*.tab,*.txt,*.csv;SQLLevel=0;
+Driver da Microsoft para arquivos texto (*.txt; *.csv) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.,*.asc,*.csv,*.tab,*.txt,*.csv;SQLLevel=0;
+Microsoft Visual FoxPro Driver UsageCount=1;APILevel=0;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.cdx,*.idx,*.fpt;SQLLevel=0;
+Microsoft FoxPro VFP Driver (*.dbf) UsageCount=1;APILevel=0;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.cdx,*.idx,*.fpt;SQLLevel=0;
+Microsoft dBase VFP Driver (*.dbf) UsageCount=1;APILevel=0;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.cdx,*.idx,*.fpt;SQLLevel=0;
+Microsoft Visual FoxPro-Treiber UsageCount=1;APILevel=0;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.cdx,*.idx,*.fpt;SQLLevel=0;
+Driver para o Microsoft Visual FoxPro UsageCount=1;APILevel=0;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.cdx,*.idx,*.fpt;SQLLevel=0;
+SQL Native Client UsageCount=1;APILevel=2;ConnectFunctions=YYY;CPTimeout=60;DriverODBCVer=09.00;FileUsage=0;SQLLevel=1;
+CR Sybase Wire Protocol ODBC Driver 6.0 UsageCount=1;APILevel=1;ConnectFunctions=YYY;DriverODBCVer=3.52;FileUsage=0;SQLLevel=0;CPTimeout=60;HelpRootDirectory=C:\Program Files\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\win32_x86\odbc\help;
+CR SQL Server Native Wire Protocol ODBC Driver 6.0 UsageCount=1;APILevel=1;ConnectFunctions=YYY;DriverODBCVer=3.52;FileUsage=0;SQLLevel=1;CPTimeout=60;HelpRootDirectory=C:\Program Files\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\win32_x86\odbc\help;
+CR SQL Server Classic Wire Protocol ODBC Driver 6.0 UsageCount=1;APILevel=1;ConnectFunctions=YYY;DriverODBCVer=3.52;FileUsage=0;SQLLevel=1;CPTimeout=60;HelpRootDirectory=C:\Program Files\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\win32_x86\odbc\help;
+CR TextFile ODBC Driver 6.0 UsageCount=1;APILevel=1;ConnectFunctions=YYY;DriverODBCVer=3.52;FileUsage=1;FileExtns=*.*;SQLLevel=0;CPTimeout=60;HelpRootDirectory=C:\Program Files\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\win32_x86\odbc\help;
+PLUGODBC_Driver UsageCount=1;
+SDB_ODBC_Driver UsageCount=2;
+Microsoft Access Text Driver (*.txt, *.csv) SQLLevel=0;FileExtns=*.txt, *.csv;FileUsage=2;DriverODBCVer=02.50;ConnectFunctions=YYN;APILevel=1;UsageCount=3;
+Microsoft Access dBASE Driver (*.dbf, *.ndx, *.mdx) SQLLevel=0;FileExtns=*.dbf, *.ndx, *.mdx;FileUsage=2;DriverODBCVer=02.50;ConnectFunctions=YYN;APILevel=1;UsageCount=3;
+Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb) SQLLevel=0;FileExtns=*.xls,*.xlsx, *.xlsb;FileUsage=2;DriverODBCVer=02.50;ConnectFunctions=YYN;APILevel=1;UsageCount=3;
+Microsoft Access Driver (*.mdb, *.accdb) SQLLevel=0;FileExtns=*.mdb,*.accdb;FileUsage=2;DriverODBCVer=02.50;ConnectFunctions=YYN;APILevel=1;UsageCount=3;
+SQLite3 ODBC Driver UsageCount=1;
+SQLite ODBC Driver UsageCount=1;
+SQLite ODBC (UTF-8) Driver UsageCount=1;
+Oracle in XE ConnectionFunctions=YYY;DriverODBCVer=03.51;CPTimeout=60;FileUsage=0;APILevel=1;SQLLevel=1;
+Oracle in instantclient_12_1 APILevel=1;ConnectionFunctions=YYY;CPTimeout=60;DriverODBCVer=03.51;FileUsage=0;SQLLevel=1;
+PostgreSQL ODBC Driver(ANSI) APILevel=1;ConnectFunctions=YYN;DriverODBCVer=09.02.0100;FileUsage=0;SQLLevel=1;
+PostgreSQL ODBC Driver(UNICODE) APILevel=1;ConnectFunctions=YYN;DriverODBCVer=09.02.0100;FileUsage=0;SQLLevel=1;
+SQL Server Native Client 11.0 UsageCount=1;APILevel=2;ConnectFunctions=YYY;CPTimeout=60;DriverODBCVer=03.80;FileUsage=0;SQLLevel=1;
+MariaDB ODBC 1.0 Driver UsageCount=1;
+Firebird/InterBase(r) driver UsageCount=1;FileExtns=*.fdb,*.gdb;APILevel=1;ConnectFunctions=YYY;FileUsage=0;DriverODBCVer=03.51;SQLLevel=1;
+MySQL ODBC 5.3 ANSI Driver UsageCount=1;
+MySQL ODBC 5.3 Unicode Driver UsageCount=1;
+DROP TABLE t1;
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Tables CONNECTION='Not important';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `Table_Cat` char(128) DEFAULT NULL,
+ `Table_Schema` char(128) DEFAULT NULL,
+ `Table_Name` char(128) NOT NULL,
+ `Table_Type` char(16) NOT NULL,
+ `Remark` char(255) DEFAULT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Tables'
+DROP TABLE t1;
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Columns CONNECTION='Not important';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `Table_Cat` char(128) DEFAULT NULL,
+ `Table_Schema` char(128) DEFAULT NULL,
+ `Table_Name` char(128) NOT NULL,
+ `Column_Name` char(128) NOT NULL,
+ `Data_Type` smallint(6) NOT NULL,
+ `Type_Name` char(30) NOT NULL,
+ `Column_Size` int(10) NOT NULL,
+ `Buffer_Length` int(10) NOT NULL,
+ `Decimal_Digits` smallint(6) DEFAULT NULL,
+ `Radix` smallint(6) DEFAULT NULL,
+ `Nullable` smallint(6) NOT NULL,
+ `Remarks` char(255) DEFAULT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Columns'
+DROP TABLE t1;
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC TABNAME='EMPLOYEE' CONNECTION='DSN=Firebird;UID=SYSDBA;PWD=masterkey';
+SELECT * FROM t1;
+EMP_NO FIRST_NAME LAST_NAME PHONE_EXT HIRE_DATE DEPT_NO JOB_CODE JOB_GRADE JOB_COUNTRY SALARY FULL_NAME
+2 Robert Nelson 250 1988-12-28 00:00:00 600 VP 2 USA 105900.00 Nelson, Robert
+4 Bruce Young 233 1988-12-28 00:00:00 621 Eng 2 USA 97500.00 Young, Bruce
+5 Kim Lambert 22 1989-02-06 00:00:00 130 Eng 2 USA 102750.00 Lambert, Kim
+8 Leslie Johnson 410 1989-04-05 00:00:00 180 Mktg 3 USA 64635.00 Johnson, Leslie
+9 Phil Forest 229 1989-04-17 00:00:00 622 Mngr 3 USA 75060.00 Forest, Phil
+11 K. J. Weston 34 1990-01-17 00:00:00 130 SRep 4 USA 86292.94 Weston, K. J.
+12 Terri Lee 256 1990-05-01 00:00:00 000 Admin 4 USA 53793.00 Lee, Terri
+14 Stewart Hall 227 1990-06-04 00:00:00 900 Finan 3 USA 69482.63 Hall, Stewart
+15 Katherine Young 231 1990-06-14 00:00:00 623 Mngr 3 USA 67241.25 Young, Katherine
+20 Chris Papadopoulos 887 1990-01-01 00:00:00 671 Mngr 3 USA 89655.00 Papadopoulos, Chris
+24 Pete Fisher 888 1990-09-12 00:00:00 671 Eng 3 USA 81810.19 Fisher, Pete
+28 Ann Bennet 5 1991-02-01 00:00:00 120 Admin 5 England 22935.00 Bennet, Ann
+29 Roger De Souza 288 1991-02-18 00:00:00 623 Eng 3 USA 69482.63 De Souza, Roger
+34 Janet Baldwin 2 1991-03-21 00:00:00 110 Sales 3 USA 61637.81 Baldwin, Janet
+36 Roger Reeves 6 1991-04-25 00:00:00 120 Sales 3 England 33620.63 Reeves, Roger
+37 Willie Stansbury 7 1991-04-25 00:00:00 120 Eng 4 England 39224.06 Stansbury, Willie
+44 Leslie Phong 216 1991-06-03 00:00:00 623 Eng 4 USA 56034.38 Phong, Leslie
+45 Ashok Ramanathan 209 1991-08-01 00:00:00 621 Eng 3 USA 80689.50 Ramanathan, Ashok
+46 Walter Steadman 210 1991-08-09 00:00:00 900 CFO 1 USA 116100.00 Steadman, Walter
+52 Carol Nordstrom 420 1991-10-02 00:00:00 180 PRel 4 USA 42742.50 Nordstrom, Carol
+61 Luke Leung 3 1992-02-18 00:00:00 110 SRep 4 USA 68805.00 Leung, Luke
+65 Sue Anne O'Brien 877 1992-03-23 00:00:00 670 Admin 5 USA 31275.00 O'Brien, Sue Anne
+71 Jennifer M. Burbank 289 1992-04-15 00:00:00 622 Eng 3 USA 53167.50 Burbank, Jennifer M.
+72 Claudia Sutherland NULL 1992-04-20 00:00:00 140 SRep 4 Canada 100914.00 Sutherland, Claudia
+83 Dana Bishop 290 1992-06-01 00:00:00 621 Eng 3 USA 62550.00 Bishop, Dana
+85 Mary S. MacDonald 477 1992-06-01 00:00:00 100 VP 2 USA 111262.50 MacDonald, Mary S.
+94 Randy Williams 892 1992-08-08 00:00:00 672 Mngr 4 USA 56295.00 Williams, Randy
+105 Oliver H. Bender 255 1992-10-08 00:00:00 000 CEO 1 USA 212850.00 Bender, Oliver H.
+107 Kevin Cook 894 1993-02-01 00:00:00 670 Dir 2 USA 111262.50 Cook, Kevin
+109 Kelly Brown 202 1993-02-04 00:00:00 600 Admin 5 USA 27000.00 Brown, Kelly
+110 Yuki Ichida 22 1993-02-04 00:00:00 115 Eng 3 Japan 6000000.00 Ichida, Yuki
+113 Mary Page 845 1993-04-12 00:00:00 671 Eng 4 USA 48000.00 Page, Mary
+114 Bill Parker 247 1993-06-01 00:00:00 623 Eng 5 USA 35000.00 Parker, Bill
+118 Takashi Yamamoto 23 1993-07-01 00:00:00 115 SRep 4 Japan 7480000.00 Yamamoto, Takashi
+121 Roberto Ferrari 1 1993-07-12 00:00:00 125 SRep 4 Italy 99000000.00 Ferrari, Roberto
+127 Michael Yanowski 492 1993-08-09 00:00:00 100 SRep 4 USA 44000.00 Yanowski, Michael
+134 Jacques Glon NULL 1993-08-23 00:00:00 123 SRep 4 France 390500.00 Glon, Jacques
+136 Scott Johnson 265 1993-09-13 00:00:00 623 Doc 3 USA 60000.00 Johnson, Scott
+138 T.J. Green 218 1993-11-01 00:00:00 621 Eng 4 USA 36000.00 Green, T.J.
+141 Pierre Osborne NULL 1994-01-03 00:00:00 121 SRep 4 Switzerland 110000.00 Osborne, Pierre
+144 John Montgomery 820 1994-03-30 00:00:00 672 Eng 5 USA 35000.00 Montgomery, John
+145 Mark Guckenheimer 221 1994-05-02 00:00:00 622 Eng 5 USA 32000.00 Guckenheimer, Mark
+DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/std_data/mdev9949.frm b/storage/connect/mysql-test/connect/std_data/mdev9949.frm
new file mode 100644
index 0000000000000000000000000000000000000000..56bb9a71263d641e532f89b3ce00ec99b77cd0a1
GIT binary patch
literal 35031
zcmeI)u}<4S7{KuhB5hzHbYMhQCXiZ13@n{!(=b&Ol`OCzh>U3E)Jo#2Wur^OQ*>ai
z)W_-Ap;EWLLW3`ch$ra6&yr*NY!5!&`M&@EJLg|*`Ptg!Xi^J5uR>^sr7&L>8u6$e
zj~jP|&2ne8ytsW=5SqXKUcX=YvHIt#@%_t_`nTR?2$SXBi#XRShsjOc7JW
z6fs3i5mUqzF-1%fQ^XW8MNAP>#1t__Oc7IL;%$rxu>m%~2D$+@zy?MGY=8{}Mc4ov
zV1wHlh#Sp8bI=@g1D|NmAc--FF9Tof`=4D+yFJSDVkgV{C)s&EF4{#Jf3_Zn&YQixZl_n>
ov|Zb--M{_e?Z?M&lqTl>h($
literal 0
HcmV?d00001
diff --git a/storage/connect/mysql-test/connect/t/drop-open-error.opt b/storage/connect/mysql-test/connect/t/drop-open-error.opt
new file mode 100644
index 00000000000..22520f0aa99
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/drop-open-error.opt
@@ -0,0 +1 @@
+--secure-file-priv=""
diff --git a/storage/connect/mysql-test/connect/t/drop-open-error.test b/storage/connect/mysql-test/connect/t/drop-open-error.test
new file mode 100644
index 00000000000..c952e016568
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/drop-open-error.test
@@ -0,0 +1,31 @@
+#
+# tests for the case when open_table_def() fails from inside
+# ha_connect::delete_or_rename_table()
+#
+#
+# MDEV-9949 Connect Engine: long SRCDEF leads to broken table
+#
+let $datadir=`select @@datadir`;
+
+create table t1 (c varchar(8));
+#error ER_VALUE_TOO_LONG;
+error ER_SQL_DISCOVER_ERROR;
+# 34K SRCDEF line:
+create table tcon engine=connect table_type=mysql CONNECTION='mysql://root@localhost/test/t1' SRCDEF='select c from t1 where c in ("foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar")';
+DROP TABLE tcon;
+
+# copy the invalid frm (as created by the statement above before the MDEV-9949 fix)
+copy_file $MTR_SUITE_DIR/std_data/mdev9949.frm $datadir/test/mdev9949.frm;
+drop table mdev9949;
+drop table t1;
+
+#
+# MDEV-7935 CREATE TABLE ... AS SELECT ... can cause a Server crash (Assertion `0' in Protocol::end_statement)
+#
+select @@secure_file_priv 'must be NULL'; # otherwise foo/bar.txt won't be allowed
+create table t1 (a char(16)) engine=myisam;
+insert into t1 values('Hello World!');
+replace_regex @on .*/foo/@on foo/@;
+error ER_GET_ERRMSG;
+create table t2 engine=connect file_name='foo/bar.txt' as select * from t1;
+drop table t1;
diff --git a/storage/connect/mysql-test/connect/t/grant2.test b/storage/connect/mysql-test/connect/t/grant2.test
index 4d136ec5f5d..8e7d9453e70 100644
--- a/storage/connect/mysql-test/connect/t/grant2.test
+++ b/storage/connect/mysql-test/connect/t/grant2.test
@@ -9,6 +9,7 @@ let $MYSQLD_DATADIR= `select @@datadir`;
--echo # MDEV-7574 Security definer views don't work with CONNECT ODBC tables
--echo #
+CREATE USER user@localhost;
GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost;
diff --git a/storage/connect/mysql-test/connect/t/infoschema-9739.test b/storage/connect/mysql-test/connect/t/infoschema-9739.test
new file mode 100644
index 00000000000..e9eb7fb796e
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/infoschema-9739.test
@@ -0,0 +1,9 @@
+#
+# MDEV-9739 Assertion `m_status == DA_ERROR || m_status == DA_OK' failed in Diagnostics_area::message() ; connect.xml* tests fail in buildbot
+#
+
+--source have_libxml2.inc
+
+create table t1 (i int) engine=Connect table_type=XML;
+select * from information_schema.tables where create_options like '%table_type=XML%';
+drop table t1;
diff --git a/storage/connect/mysql-test/connect/t/mysql_new.test b/storage/connect/mysql-test/connect/t/mysql_new.test
index c93f0407ca4..de9cae7b87b 100644
--- a/storage/connect/mysql-test/connect/t/mysql_new.test
+++ b/storage/connect/mysql-test/connect/t/mysql_new.test
@@ -304,7 +304,7 @@ DROP TABLE t1;
--echo # Testing temporal data types
--echo #
-CREATE TABLE t1 (a date, b datetime, c time, d timestamp, e year);
+CREATE TABLE t1 (a date, b datetime, c time, d timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, e year);
SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES('2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23');
SELECT * FROM t1;
diff --git a/storage/connect/mysql-test/connect/t/odbc_firebird.test b/storage/connect/mysql-test/connect/t/odbc_firebird.test
new file mode 100644
index 00000000000..c9279eec385
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/odbc_firebird.test
@@ -0,0 +1,35 @@
+--source have_odbc.inc
+
+SET NAMES utf8;
+
+# MS ODBC and unixODBC return different error message text,
+# so disable displaying error messages
+--disable_result_log ONCE
+--error ER_UNKNOWN_ERROR
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Bad connection string';
+
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources;
+if (`select count(*)=0 from t1 where name='firebird'`) {
+ DROP TABLE t1;
+ skip No Firebird;
+}
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers;
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Tables CONNECTION='Not important';
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Columns CONNECTION='Not important';
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC TABNAME='EMPLOYEE' CONNECTION='DSN=Firebird;UID=SYSDBA;PWD=masterkey';
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/t/secure_file_priv.test b/storage/connect/mysql-test/connect/t/secure_file_priv.test
index 46633502034..f7792536892 100644
--- a/storage/connect/mysql-test/connect/t/secure_file_priv.test
+++ b/storage/connect/mysql-test/connect/t/secure_file_priv.test
@@ -10,4 +10,4 @@ let $SECUREDIR= `select @@secure_file_priv`;
INSERT INTO t1 VALUES (10);
SELECT * FROM t1;
DROP TABLE t1;
---remove_file $SECUREDIR/t1.dbf
+--remove_file $MYSQL_TMP_DIR/t1.dbf
diff --git a/storage/connect/noconst.c b/storage/connect/noconst.c
new file mode 100644
index 00000000000..043eae7c54e
--- /dev/null
+++ b/storage/connect/noconst.c
@@ -0,0 +1,38 @@
+/***********************************************************************/
+/* (C) Copyright to the author Olivier BERTRAND 2015 */
+/***********************************************************************/
+#include
+#include
+#include
+
+#if defined(__WIN__)
+#define DllExport __declspec( dllexport )
+#else // !__WIN__
+#define DllExport
+#endif // !__WIN__
+
+extern "C" {
+ DllExport my_bool noconst_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char *noconst(UDF_INIT*, UDF_ARGS*, char*, unsigned long*, char*, char*);
+} // extern "C"
+
+/***********************************************************************/
+/* Returns its argument saying it is not a constant. */
+/***********************************************************************/
+my_bool noconst_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ if (args->arg_count != 1 || args->arg_type[0] != STRING_RESULT) {
+ strcpy(message, "noconst unique argument must be a string");
+ return true;
+ } // endif arg
+
+ initid->const_item = false; // The trick!
+ return false;
+} // end of noconst_init
+
+char *noconst(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *, char *)
+{
+ return args->args[0];
+} // end of noconst
+
diff --git a/storage/connect/os.h b/storage/connect/os.h
index 8056a272990..e2b165fb3f5 100644
--- a/storage/connect/os.h
+++ b/storage/connect/os.h
@@ -1,3 +1,4 @@
+/* Copyright (C) MariaDB Corporation Ab */
#ifndef _OS_H_INCLUDED
#define _OS_H_INCLUDED
diff --git a/storage/connect/osutil.c b/storage/connect/osutil.c
index 66743c7403b..da896fec50e 100644
--- a/storage/connect/osutil.c
+++ b/storage/connect/osutil.c
@@ -1,3 +1,4 @@
+/* Copyright (C) MariaDB Corporation Ab */
#include "my_global.h"
#include
#include
diff --git a/storage/connect/osutil.h b/storage/connect/osutil.h
index ac63d4ee973..7e6b8823b9b 100644
--- a/storage/connect/osutil.h
+++ b/storage/connect/osutil.h
@@ -1,3 +1,4 @@
+/* Copyright (C) MariaDB Corporation Ab */
#ifndef __OSUTIL_H__
#define __OSUTIL_H__
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index 2198c44c200..5729b5bd6ff 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -36,8 +36,6 @@ enum BLKTYP {TYPE_TABLE = 50, /* Table Name/Srcdef/... Block */
TYPE_COLCRT = 71, /* Column creation block */
TYPE_CONST = 72, /* Constant */
-/*-------------------- type tokenized string --------------------------*/
- TYPE_DATE = 8, /* Timestamp */
/*-------------------- additional values used by LNA ------------------*/
TYPE_COLIST = 14, /* Column list */
TYPE_COL = 41, /* Column */
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index b6f59bac8cf..03a326ce89a 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -82,14 +82,10 @@ extern "C" {
extern char version[];
} // extern "C"
-#if defined(__WIN__)
-extern CRITICAL_SECTION parsec; // Used calling the Flex parser
-#else // !__WIN__
extern pthread_mutex_t parmut;
-#endif // !__WIN__
// The debug trace used by the main thread
- FILE *pfile = NULL;
+FILE *pfile = NULL;
MBLOCK Nmblk = {NULL, false, 0, false, NULL}; // Used to init MBLOCK's
@@ -473,7 +469,7 @@ bool PlugEvalLike(PGLOBAL g, LPCSTR strg, LPCSTR pat, bool ci)
tp = g->Message;
else if (!(tp = new char[strlen(pat) + strlen(strg) + 2])) {
strcpy(g->Message, MSG(NEW_RETURN_NULL));
- throw OP_LIKE;
+ throw (int)OP_LIKE;
} /* endif tp */
sp = tp + strlen(pat) + 1;
@@ -484,7 +480,7 @@ bool PlugEvalLike(PGLOBAL g, LPCSTR strg, LPCSTR pat, bool ci)
tp = g->Message; /* Use this as temporary work space. */
else if (!(tp = new char[strlen(pat) + 1])) {
strcpy(g->Message, MSG(NEW_RETURN_NULL));
- throw OP_LIKE;
+ throw (int)OP_LIKE;
} /* endif tp */
strcpy(tp, pat); /* Make a copy to be worked into */
@@ -697,21 +693,9 @@ PDTP MakeDateFormat(PGLOBAL g, PCSZ dfmt, bool in, bool out, int flag)
/* Call the FLEX generated parser. In multi-threading mode the next */
/* instruction is included in an Enter/LeaveCriticalSection bracket. */
/*********************************************************************/
- //#if defined(THREAD)
-#if defined(__WIN__)
- EnterCriticalSection((LPCRITICAL_SECTION)&parsec);
-#else // !__WIN__
pthread_mutex_lock(&parmut);
-#endif // !__WIN__
-//#endif // THREAD
rc = fmdflex(pdp);
-//#if defined(THREAD)
-#if defined(__WIN__)
- LeaveCriticalSection((LPCRITICAL_SECTION)&parsec);
-#else // !__WIN__
pthread_mutex_unlock(&parmut);
-#endif // !__WIN__
-//#endif // THREAD
if (trace)
htrc("Done: in=%s out=%s rc=%d\n", SVP(pdp->InFmt), SVP(pdp->OutFmt), rc);
diff --git a/storage/connect/plugutil.cpp b/storage/connect/plugutil.cpp
index f0822526b98..e4bfd825932 100644
--- a/storage/connect/plugutil.cpp
+++ b/storage/connect/plugutil.cpp
@@ -2,11 +2,11 @@
/* */
/* PROGRAM NAME: PLUGUTIL */
/* ------------- */
-/* Version 2.9 */
+/* Version 3.0 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1993-2015 */
+/* (C) Copyright to the author Olivier BERTRAND 1993-2017 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -76,6 +76,7 @@
#include "osutil.h"
#include "global.h"
+#include "plgdbsem.h"
#if defined(NEWMSG)
#include "rcmsg.h"
#endif // NEWMSG
@@ -132,12 +133,12 @@ void htrc(char const *fmt, ...)
/* Return value is the pointer to the Global structure. */
/***********************************************************************/
PGLOBAL PlugInit(LPCSTR Language, uint worksize)
- {
- PGLOBAL g;
+{
+ PGLOBAL g;
- if (trace > 1)
- htrc("PlugInit: Language='%s'\n",
- ((!Language) ? "Null" : (char*)Language));
+ if (trace > 1)
+ htrc("PlugInit: Language='%s'\n",
+ ((!Language) ? "Null" : (char*)Language));
try {
g = new GLOBAL;
@@ -146,53 +147,54 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
return NULL;
} // end try/catch
- //if (!(g = (PGLOBAL)malloc(sizeof(GLOBAL)))) {
- // fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL));
- // return NULL;
- // } else {
- g->Sarea = NULL;
- g->Createas = 0;
- g->Alchecked = 0;
- g->Mrr = 0;
- g->Activityp = NULL;
- g->Xchk = NULL;
- g->N = 0;
- g->More = 0;
- strcpy(g->Message, "");
+ g->Sarea = NULL;
+ g->Createas = 0;
+ g->Alchecked = 0;
+ g->Mrr = 0;
+ g->Activityp = NULL;
+ g->Xchk = NULL;
+ g->N = 0;
+ g->More = 0;
+ strcpy(g->Message, "");
- /*******************************************************************/
- /* Allocate the main work segment. */
- /*******************************************************************/
- if (worksize && !(g->Sarea = PlugAllocMem(g, worksize))) {
- char errmsg[MAX_STR];
- sprintf(errmsg, MSG(WORK_AREA), g->Message);
- strcpy(g->Message, errmsg);
- g->Sarea_Size = 0;
- } else
- g->Sarea_Size = worksize;
+ /*******************************************************************/
+ /* Allocate the main work segment. */
+ /*******************************************************************/
+ if (worksize && !(g->Sarea = PlugAllocMem(g, worksize))) {
+ char errmsg[MAX_STR];
+ sprintf(errmsg, MSG(WORK_AREA), g->Message);
+ strcpy(g->Message, errmsg);
+ g->Sarea_Size = 0;
+ } else
+ g->Sarea_Size = worksize;
- //} /* endif g */
-
- g->jump_level = -1; /* New setting to allow recursive call of Plug */
- return(g);
- } /* end of PlugInit */
+ g->jump_level = -1; /* New setting to allow recursive call of Plug */
+ return(g);
+} /* end of PlugInit */
/***********************************************************************/
/* PlugExit: Terminate Plug operations. */
/***********************************************************************/
int PlugExit(PGLOBAL g)
- {
- int rc = 0;
+{
+ if (g) {
+ PDBUSER dup = PlgGetUser(g);
- if (!g)
- return rc;
+ if (dup)
+ free(dup);
- if (g->Sarea)
- free(g->Sarea);
+ if (g->Sarea) {
+ if (trace)
+ htrc("Freeing Sarea size=%d\n", g->Sarea_Size);
- delete g;
- return rc;
- } /* end of PlugExit */
+ free(g->Sarea);
+ } // endif Sarea
+
+ delete g;
+ } // endif g
+
+ return 0;
+} // end of PlugExit
/***********************************************************************/
/* Remove the file type from a file name. */
@@ -456,7 +458,7 @@ short GetLineLength(PGLOBAL g)
/* Program for memory allocation of work and language areas. */
/***********************************************************************/
void *PlugAllocMem(PGLOBAL g, uint size)
- {
+{
void *areap; /* Pointer to allocated area */
/*********************************************************************/
@@ -465,16 +467,16 @@ void *PlugAllocMem(PGLOBAL g, uint size)
if (!(areap = malloc(size)))
sprintf(g->Message, MSG(MALLOC_ERROR), "malloc");
- if (trace > 1) {
+ if (trace) {
if (areap)
htrc("Memory of %u allocated at %p\n", size, areap);
else
htrc("PlugAllocMem: %s\n", g->Message);
- } // endif trace
+ } // endif trace
return (areap);
- } /* end of PlugAllocMem */
+} // end of PlugAllocMem
/***********************************************************************/
/* Program for SubSet initialization of memory pools. */
diff --git a/storage/connect/tabcol.cpp b/storage/connect/tabcol.cpp
index 2740864a69b..5065d86ce6a 100644
--- a/storage/connect/tabcol.cpp
+++ b/storage/connect/tabcol.cpp
@@ -86,7 +86,7 @@ void XTAB::Printf(PGLOBAL g, FILE *f, uint n)
PlugPutOut(g, f, TYPE_TDB, tp->To_Tdb, n + 2);
} /* endfor tp */
- } /* end of Print */
+ } /* end of Printf */
/***********************************************************************/
/* Make string output of XTAB contents. */
@@ -105,7 +105,7 @@ void XTAB::Prints(PGLOBAL, char *ps, uint z)
n -= i;
} // endif tp
- } /* end of Print */
+ } /* end of Prints */
/***********************************************************************/
@@ -149,7 +149,7 @@ void COLUMN::Printf(PGLOBAL g, FILE *f, uint n)
PlugPutOut(g, f, TYPE_TABLE, To_Table, n + 2);
PlugPutOut(g, f, TYPE_XOBJECT, To_Col, n + 2);
- } /* end of Print */
+ } /* end of Printf */
/***********************************************************************/
/* Make string output of COLUMN contents. */
@@ -166,4 +166,4 @@ void COLUMN::Prints(PGLOBAL, char *ps, uint z)
strncpy(ps, buf, z);
ps[z - 1] = '\0';
- } /* end of Print */
+ } /* end of Prints */
diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp
index 468966e79d9..37e53c83d36 100644
--- a/storage/connect/tabdos.cpp
+++ b/storage/connect/tabdos.cpp
@@ -1309,7 +1309,7 @@ PBF TDBDOS::InitBlockFilter(PGLOBAL g, PFIL filp)
} // endif !opm
// if opm, pass thru
- /* fall through */
+ // fall through
case OP_IN:
if (filp->GetArgType(0) == TYPE_COLBLK &&
filp->GetArgType(1) == TYPE_ARRAY) {
@@ -1645,8 +1645,8 @@ int TDBDOS::TestBlock(PGLOBAL g)
/***********************************************************************/
int TDBDOS::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
{
- int k, n;
- bool fixed, doit, sep, b = (pxdf != NULL);
+ int k, n, rc = RC_OK;
+ bool fixed, doit, sep, b = (pxdf != NULL);
PCOL *keycols, colp;
PIXDEF xdp, sxp = NULL;
PKPDEF kdp;
@@ -1690,95 +1690,105 @@ int TDBDOS::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
} else if (!(pxdf = dfp->GetIndx()))
return RC_INFO; // No index to make
- // Allocate all columns that will be used by indexes.
- // This must be done before opening the table so specific
- // column initialization can be done (in particular by TDBVCT)
- for (n = 0, xdp = pxdf; xdp; xdp = xdp->GetNext())
- for (kdp = xdp->GetToKeyParts(); kdp; kdp = kdp->GetNext()) {
- if (!(colp = ColDB(g, kdp->GetName(), 0))) {
- sprintf(g->Message, MSG(INDX_COL_NOTIN), kdp->GetName(), Name);
- goto err;
- } else if (colp->GetResultType() == TYPE_DECIM) {
- sprintf(g->Message, "Decimal columns are not indexable yet");
- goto err;
- } // endif Type
+ try {
+ // Allocate all columns that will be used by indexes.
+ // This must be done before opening the table so specific
+ // column initialization can be done (in particular by TDBVCT)
+ for (n = 0, xdp = pxdf; xdp; xdp = xdp->GetNext())
+ for (kdp = xdp->GetToKeyParts(); kdp; kdp = kdp->GetNext()) {
+ if (!(colp = ColDB(g, kdp->GetName(), 0))) {
+ sprintf(g->Message, MSG(INDX_COL_NOTIN), kdp->GetName(), Name);
+ goto err;
+ } else if (colp->GetResultType() == TYPE_DECIM) {
+ sprintf(g->Message, "Decimal columns are not indexable yet");
+ goto err;
+ } // endif Type
- colp->InitValue(g);
- n = MY_MAX(n, xdp->GetNparts());
- } // endfor kdp
+ colp->InitValue(g);
+ n = MY_MAX(n, xdp->GetNparts());
+ } // endfor kdp
- keycols = (PCOL*)PlugSubAlloc(g, NULL, n * sizeof(PCOL));
- sep = dfp->GetBoolCatInfo("SepIndex", false);
+ keycols = (PCOL*)PlugSubAlloc(g, NULL, n * sizeof(PCOL));
+ sep = dfp->GetBoolCatInfo("SepIndex", false);
- /*********************************************************************/
- /* Construct and save the defined indexes. */
- /*********************************************************************/
- for (xdp = pxdf; xdp; xdp = xdp->GetNext())
- if (!OpenDB(g)) {
- if (xdp->IsAuto() && fixed)
- // Auto increment key and fixed file: use an XXROW index
- continue; // XXROW index doesn't need to be made
+ /*********************************************************************/
+ /* Construct and save the defined indexes. */
+ /*********************************************************************/
+ for (xdp = pxdf; xdp; xdp = xdp->GetNext())
+ if (!OpenDB(g)) {
+ if (xdp->IsAuto() && fixed)
+ // Auto increment key and fixed file: use an XXROW index
+ continue; // XXROW index doesn't need to be made
- // On Update, redo only indexes that are modified
- doit = !To_SetCols;
- n = 0;
+ // On Update, redo only indexes that are modified
+ doit = !To_SetCols;
+ n = 0;
- if (sxp)
- xdp->SetID(sxp->GetID() + 1);
+ if (sxp)
+ xdp->SetID(sxp->GetID() + 1);
- for (kdp = xdp->GetToKeyParts(); kdp; kdp = kdp->GetNext()) {
- // Check whether this column was updated
- for (colp = To_SetCols; !doit && colp; colp = colp->GetNext())
- if (!stricmp(kdp->GetName(), colp->GetName()))
- doit = true;
+ for (kdp = xdp->GetToKeyParts(); kdp; kdp = kdp->GetNext()) {
+ // Check whether this column was updated
+ for (colp = To_SetCols; !doit && colp; colp = colp->GetNext())
+ if (!stricmp(kdp->GetName(), colp->GetName()))
+ doit = true;
- keycols[n++] = ColDB(g, kdp->GetName(), 0);
- } // endfor kdp
+ keycols[n++] = ColDB(g, kdp->GetName(), 0);
+ } // endfor kdp
- // If no indexed columns were updated, don't remake the index
- // if indexes are in separate files.
- if (!doit && sep)
- continue;
+ // If no indexed columns were updated, don't remake the index
+ // if indexes are in separate files.
+ if (!doit && sep)
+ continue;
- k = xdp->GetNparts();
+ k = xdp->GetNparts();
- // Make the index and save it
- if (dfp->Huge)
- pxp = new(g) XHUGE;
- else
- pxp = new(g) XFILE;
+ // Make the index and save it
+ if (dfp->Huge)
+ pxp = new(g) XHUGE;
+ else
+ pxp = new(g) XFILE;
- if (k == 1) // Simple index
- x = new(g) XINDXS(this, xdp, pxp, keycols);
- else // Multi-Column index
- x = new(g) XINDEX(this, xdp, pxp, keycols);
+ if (k == 1) // Simple index
+ x = new(g) XINDXS(this, xdp, pxp, keycols);
+ else // Multi-Column index
+ x = new(g) XINDEX(this, xdp, pxp, keycols);
- if (!x->Make(g, sxp)) {
- // Retreive define values from the index
- xdp->SetMaxSame(x->GetMaxSame());
-// xdp->SetSize(x->GetSize());
+ if (!x->Make(g, sxp)) {
+ // Retreive define values from the index
+ xdp->SetMaxSame(x->GetMaxSame());
+ // xdp->SetSize(x->GetSize());
- // store KXYCOL Mxs in KPARTDEF Mxsame
- xdp->SetMxsame(x);
+ // store KXYCOL Mxs in KPARTDEF Mxsame
+ xdp->SetMxsame(x);
#if defined(TRACE)
- printf("Make done...\n");
+ printf("Make done...\n");
#endif // TRACE
-// if (x->GetSize() > 0)
- sxp = xdp;
+ // if (x->GetSize() > 0)
+ sxp = xdp;
- xdp->SetInvalid(false);
- } else
- goto err;
+ xdp->SetInvalid(false);
+ } else
+ goto err;
- } else
- return RC_INFO; // Error or Physical table does not exist
+ } else
+ return RC_INFO; // Error or Physical table does not exist
+
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ rc = RC_FX;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ rc = RC_FX;
+ } // end catch
if (Use == USE_OPEN)
CloseDB(g);
- return RC_OK;
+ return rc;
err:
if (sxp)
@@ -2725,7 +2735,7 @@ void DOSCOL::WriteColumn(PGLOBAL g)
if (Value->GetBinValue(p, Long, Status)) {
sprintf(g->Message, MSG(BIN_F_TOO_LONG),
Name, Value->GetSize(), Long);
- longjmp(g->jumper[g->jump_level], 31);
+ throw 31;
} // endif
} // end of WriteColumn
@@ -2874,7 +2884,7 @@ bool DOSCOL::AddDistinctValue(PGLOBAL g)
void DOSCOL::Printf(PGLOBAL g, FILE *f, uint n)
{
COLBLK::Printf(g, f, n);
- } // end of Print
+ } // end of Printf
/* ------------------------------------------------------------------- */
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index 063115c7a60..a74be7eb699 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -41,12 +41,12 @@
/***********************************************************************/
#define MAXCOL 200 /* Default max column nb in result */
#define TYPE_UNKNOWN 12 /* Must be greater than other types */
-#define USE_G 1 /* Use recoverable memory if 1 */
/***********************************************************************/
/* External function. */
/***********************************************************************/
USETEMP UseTemp(void);
+char *GetJsonNull(void);
typedef struct _jncol {
struct _jncol *Next;
@@ -163,7 +163,6 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info)
tjnp->SetMode(MODE_READ);
-#if USE_G
// Allocate the parse work memory
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
memset(G, 0, sizeof(GLOBAL));
@@ -172,9 +171,6 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info)
PlugSubSet(G, G->Sarea, G->Sarea_Size);
G->jump_level = 0;
tjnp->SetG(G);
-#else
- tjnp->SetG(g);
-#endif
if (tjnp->OpenDB(g))
return NULL;
@@ -478,7 +474,6 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
// Txfp must be set for TDBDOS
tdbp = new(g) TDBJSN(this, txfp);
-#if USE_G
// Allocate the parse work memory
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
memset(G, 0, sizeof(GLOBAL));
@@ -487,9 +482,6 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
PlugSubSet(G, G->Sarea, G->Sarea_Size);
G->jump_level = 0;
((TDBJSN*)tdbp)->G = G;
-#else
- ((TDBJSN*)tdbp)->G = g;
-#endif
} else {
if (Zipped) {
#if defined(ZIP_SUPPORT)
@@ -762,10 +754,8 @@ int TDBJSN::ReadDB(PGLOBAL g)
// Deferred reading failed
return rc;
-#if USE_G
// Recover the memory used for parsing
PlugSubSet(G, G->Sarea, G->Sarea_Size);
-#endif
if ((Row = ParseJson(G, To_Line, strlen(To_Line), &Pretty, &Comma))) {
Row = FindRow(g);
@@ -774,9 +764,7 @@ int TDBJSN::ReadDB(PGLOBAL g)
M = 1;
rc = RC_OK;
} else if (Pretty != 1 || strcmp(To_Line, "]")) {
-#if USE_G
strcpy(g->Message, G->Message);
-#endif
rc = RC_FX;
} else
rc = RC_EF;
@@ -882,9 +870,7 @@ int TDBJSN::WriteDB(PGLOBAL g)
{
int rc = TDBDOS::WriteDB(g);
-#if USE_G
PlugSubSet(G, G->Sarea, G->Sarea_Size);
-#endif
Row->Clear();
return rc;
} // end of WriteDB
@@ -1228,7 +1214,7 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
case TYPE_INTG:
case TYPE_BINT:
case TYPE_DBL:
- case TYPE_DATE:
+ case TYPE_DTM:
vp->SetValue_pval(val->GetValue());
break;
case TYPE_BOOL:
@@ -1390,9 +1376,12 @@ PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n)
for (i = 0; i < ars; i++) {
jvrp = arp->GetValue(i);
- do {
- if (n < Nod - 1 && jvrp->GetJson()) {
- Tjp->NextSame = nextsame;
+ if (!jvrp->IsNull() || (op == OP_CNC && GetJsonNull())) do {
+ if (jvrp->IsNull()) {
+ jvrp->Value = AllocateValue(g, GetJsonNull(), TYPE_STRING);
+ jvp = jvrp;
+ } else if (n < Nod - 1 && jvrp->GetJson()) {
+ Tjp->NextSame = nextsame;
jval.SetValue(GetColumnValue(g, jvrp->GetJson(), n + 1));
jvp = &jval;
} else
@@ -1404,8 +1393,9 @@ PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n)
} else
SetJsonValue(g, MulVal, jvp, n);
- if (!MulVal->IsZero()) {
- switch (op) {
+// if (!MulVal->IsZero()) {
+ if (!MulVal->IsNull()) {
+ switch (op) {
case OP_CNC:
if (Nodes[n].CncVal) {
val[0] = Nodes[n].CncVal;
diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp
index d39837a7b5a..c3a02ff42b9 100644
--- a/storage/connect/table.cpp
+++ b/storage/connect/table.cpp
@@ -324,7 +324,7 @@ void TDB::Printf(PGLOBAL g, FILE *f, uint n)
void TDB::Prints(PGLOBAL, char *ps, uint)
{
sprintf(ps, "R%d.%s", Tdb_No, Name);
- } // end of Print
+ } // end of Prints
/* -------------------------- class TDBASE --------------------------- */
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index 34711d584f1..8ffa234ba5c 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -273,7 +273,7 @@ PCSZ TDBODBC::GetFile(PGLOBAL g)
/***********************************************************************/
/* Set DBQ and get the new file name into the connect string. */
/***********************************************************************/
-void TDBODBC::SetFile(PGLOBAL g, PSZ fn)
+void TDBODBC::SetFile(PGLOBAL g, PCSZ fn)
{
if (MulConn) {
int n = strlen(MulConn) + strlen(fn) - 1;
@@ -289,7 +289,7 @@ void TDBODBC::SetFile(PGLOBAL g, PSZ fn)
sprintf(Connect, MulConn, fn);
} // endif MultConn
- DBQ = fn;
+ DBQ = PlugDup(g, fn);
} // end of SetFile
/***********************************************************************/
diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h
index 0ca88b60858..0699da54e7f 100644
--- a/storage/connect/tabodbc.h
+++ b/storage/connect/tabodbc.h
@@ -71,7 +71,7 @@ class TDBODBC : public TDBEXT {
virtual PTDB Clone(PTABS t);
virtual bool SetRecpos(PGLOBAL g, int recpos);
virtual PCSZ GetFile(PGLOBAL g);
- virtual void SetFile(PGLOBAL g, PSZ fn);
+ virtual void SetFile(PGLOBAL g, PCSZ fn);
virtual void ResetSize(void);
virtual PCSZ GetServer(void) {return "ODBC";}
virtual int Indexable(void) {return 2;}
diff --git a/storage/connect/tabvir.cpp b/storage/connect/tabvir.cpp
index 84b3dd1787b..c78a8f531f6 100644
--- a/storage/connect/tabvir.cpp
+++ b/storage/connect/tabvir.cpp
@@ -289,7 +289,7 @@ void VIRCOL::ReadColumn(PGLOBAL g)
{
// This should never be called
sprintf(g->Message, "ReadColumn: Column %s is not virtual", Name);
- throw TYPE_COLBLK;
+ throw (int)TYPE_COLBLK;
} // end of ReadColumn
/* ---------------------------TDBVICL class -------------------------- */
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index 80d4395058e..c09386451ff 100644
--- a/storage/connect/tabxml.cpp
+++ b/storage/connect/tabxml.cpp
@@ -1319,7 +1319,7 @@ void TDBXML::CloseDB(PGLOBAL g)
Docp->CloseDoc(g, To_Xb);
// This causes a crash in Diagnostics_area::set_error_status
-// throw TYPE_AM_XML;
+// throw (int)TYPE_AM_XML;
} // endif DumpDoc
} // endif Changed
@@ -1642,7 +1642,7 @@ void XMLCOL::ReadColumn(PGLOBAL g)
if (ValNode->GetType() != XML_ELEMENT_NODE &&
ValNode->GetType() != XML_ATTRIBUTE_NODE) {
sprintf(g->Message, MSG(BAD_VALNODE), ValNode->GetType(), Name);
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} // endif type
// Get the Xname value from the XML file
@@ -1653,7 +1653,7 @@ void XMLCOL::ReadColumn(PGLOBAL g)
PushWarning(g, Tdbp);
break;
default:
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} // endswitch
Value->SetValue_psz(Valbuf);
@@ -1704,7 +1704,7 @@ void XMLCOL::WriteColumn(PGLOBAL g)
/* For columns having an Xpath, the Clist must be updated. */
/*********************************************************************/
if (Tdbp->CheckRow(g, Nod || Tdbp->Colname))
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
/*********************************************************************/
/* Null values are represented by no node. */
@@ -1776,7 +1776,7 @@ void XMLCOL::WriteColumn(PGLOBAL g)
if (ColNode == NULL) {
strcpy(g->Message, MSG(COL_ALLOC_ERR));
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} // endif ColNode
} // endif ColNode
@@ -1795,7 +1795,7 @@ void XMLCOL::WriteColumn(PGLOBAL g)
if (ValNode == NULL && AttNode == NULL) {
strcpy(g->Message, MSG(VAL_ALLOC_ERR));
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
+ throw (int)TYPE_AM_XML;
} // endif ValNode
/*********************************************************************/
@@ -1805,7 +1805,7 @@ void XMLCOL::WriteColumn(PGLOBAL g)
if (strlen(p) > (unsigned)Long) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long);
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} else
strcpy(Valbuf, p);
@@ -1855,7 +1855,7 @@ void XMULCOL::ReadColumn(PGLOBAL g)
if (ValNode->GetType() != XML_ELEMENT_NODE &&
ValNode->GetType() != XML_ATTRIBUTE_NODE) {
sprintf(g->Message, MSG(BAD_VALNODE), ValNode->GetType(), Name);
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} // endif type
// Get the Xname value from the XML file
@@ -1866,7 +1866,7 @@ void XMULCOL::ReadColumn(PGLOBAL g)
PushWarning(g, Tdbp);
break;
default:
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
+ throw (int)TYPE_AM_XML;
} // endswitch
if (!b) {
@@ -1941,7 +1941,7 @@ void XMULCOL::WriteColumn(PGLOBAL g)
/* For columns having an Xpath, the Clist must be updated. */
/*********************************************************************/
if (Tdbp->CheckRow(g, Nod))
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
/*********************************************************************/
/* Find the column and value nodes to update or insert. */
@@ -1990,7 +1990,7 @@ void XMULCOL::WriteColumn(PGLOBAL g)
if (len > 1 && !Tdbp->Xpand) {
sprintf(g->Message, MSG(BAD_VAL_UPDATE), Name);
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} else
ValNode = Nlx->GetItem(g, Tdbp->Nsub, Vxnp);
@@ -2032,7 +2032,7 @@ void XMULCOL::WriteColumn(PGLOBAL g)
if (ColNode == NULL) {
strcpy(g->Message, MSG(COL_ALLOC_ERR));
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} // endif ColNode
} // endif ColNode
@@ -2051,8 +2051,8 @@ void XMULCOL::WriteColumn(PGLOBAL g)
if (ValNode == NULL && AttNode == NULL) {
strcpy(g->Message, MSG(VAL_ALLOC_ERR));
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endif ValNode
+ throw (int)TYPE_AM_XML;
+ } // endif ValNode
/*********************************************************************/
/* Get the string representation of Value according to column type. */
@@ -2061,7 +2061,7 @@ void XMULCOL::WriteColumn(PGLOBAL g)
if (strlen(p) > (unsigned)Long) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long);
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} else
strcpy(Valbuf, p);
@@ -2093,7 +2093,7 @@ void XPOSCOL::ReadColumn(PGLOBAL g)
if (Tdbp->Clist == NULL) {
strcpy(g->Message, MSG(MIS_TAG_LIST));
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} // endif Clist
if ((ValNode = Tdbp->Clist->GetItem(g, Rank, Vxnp))) {
@@ -2105,7 +2105,7 @@ void XPOSCOL::ReadColumn(PGLOBAL g)
PushWarning(g, Tdbp);
break;
default:
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} // endswitch
Value->SetValue_psz(Valbuf);
@@ -2156,14 +2156,14 @@ void XPOSCOL::WriteColumn(PGLOBAL g)
/* For all columns the Clist must be updated. */
/*********************************************************************/
if (Tdbp->CheckRow(g, true))
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
/*********************************************************************/
/* Find the column and value nodes to update or insert. */
/*********************************************************************/
if (Tdbp->Clist == NULL) {
strcpy(g->Message, MSG(MIS_TAG_LIST));
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} // endif Clist
n = Tdbp->Clist->GetLength();
@@ -2188,7 +2188,7 @@ void XPOSCOL::WriteColumn(PGLOBAL g)
if (strlen(p) > (unsigned)Long) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long);
- throw TYPE_AM_XML;
+ throw (int)TYPE_AM_XML;
} else
strcpy(Valbuf, p);
diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc
index ca3557666a4..9fe2c75d530 100644
--- a/storage/connect/user_connect.cc
+++ b/storage/connect/user_connect.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2015
+/* Copyright (C) MariaDB Corporation Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
that is a connection with its personnal memory allocation.
@note
-
+ Author Olivier Bertrand
*/
/****************************************************************************/
@@ -47,6 +47,8 @@
#include "user_connect.h"
#include "mycat.h"
+extern pthread_mutex_t usrmut;
+
/****************************************************************************/
/* Initialize the user_connect static member. */
/****************************************************************************/
@@ -111,7 +113,10 @@ bool user_connect::user_init()
int rc= PlugExit(g);
g= NULL;
- free(dup);
+
+ if (dup)
+ free(dup);
+
return true;
} // endif g->
@@ -122,15 +127,19 @@ bool user_connect::user_init()
strcpy(ap->Ap_Name, "CONNECT");
g->Activityp= ap;
g->Activityp->Aptr= dup;
- next= to_users;
+
+ pthread_mutex_lock(&usrmut);
+ next= to_users;
to_users= this;
if (next)
next->previous= this;
- last_query_id= thdp->query_id;
count= 1;
- return false;
+ pthread_mutex_unlock(&usrmut);
+
+ last_query_id = thdp->query_id;
+ return false;
} // end of user_init
@@ -144,18 +153,22 @@ void user_connect::SetHandler(ha_connect *hc)
/****************************************************************************/
/* Check whether we begin a new query and if so cleanup the previous one. */
/****************************************************************************/
-bool user_connect::CheckCleanup(void)
+bool user_connect::CheckCleanup(bool force)
{
- if (thdp->query_id > last_query_id) {
+ if (thdp->query_id > last_query_id || force) {
uint worksize= GetWorkSize();
PlugCleanup(g, true);
if (g->Sarea_Size != worksize) {
- if (g->Sarea)
- free(g->Sarea);
+ if (g->Sarea) {
+ if (trace)
+ htrc("CheckCleanup: Free Sarea %d\n", g->Sarea_Size);
- // Check whether the work area size was changed
+ free(g->Sarea);
+ } // endif Size
+
+ // Check whether the work area could be allocated
if (!(g->Sarea = PlugAllocMem(g, worksize))) {
g->Sarea = PlugAllocMem(g, g->Sarea_Size);
SetWorkSize(g->Sarea_Size); // Was too big
@@ -171,7 +184,7 @@ bool user_connect::CheckCleanup(void)
g->Mrr = 0;
last_query_id= thdp->query_id;
- if (trace)
+ if (trace && !force)
printf("=====> Begin new query %llu\n", last_query_id);
return true;
diff --git a/storage/connect/user_connect.h b/storage/connect/user_connect.h
index a883eb85934..983d9adc478 100644
--- a/storage/connect/user_connect.h
+++ b/storage/connect/user_connect.h
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2011
+/* Copyright (C) MariaDB Corporation Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
Declaration of the user_connect class.
@note
+ Author Olivier Bertrand
@see
/sql/handler.h and /storage/connect/user_connect.cc
@@ -53,7 +54,7 @@ public:
// Implementation
bool user_init();
void SetHandler(ha_connect *hc);
- bool CheckCleanup(void);
+ bool CheckCleanup(bool force = false);
bool CheckQueryID(void) {return thdp->query_id > last_query_id;}
bool CheckQuery(query_id_t vid) {return last_query_id > vid;}
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index b6c63bdadd3..8316e7a5ff0 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -118,7 +118,8 @@ ulonglong CharToNumber(const char *p, int n, ulonglong maxval,
maxval++;
if (minus) *minus = true;
} // endif Unsigned
- /* fall through */
+
+ // Fall through
case '+':
p++;
break;
@@ -571,9 +572,9 @@ void VALUE::Printf(PGLOBAL g, FILE *f, uint n)
if (Null)
fprintf(f, "%s\n", m);
else
- fprintf(f, "%s%s%s", GetCharString(buf), "\n", m);
+ fprintf(f, "%s%s\n", m, GetCharString(buf));
-} /* end of Print */
+} /* end of Printf */
/***********************************************************************/
/* Make string output of an object value. */
@@ -588,7 +589,7 @@ void VALUE::Prints(PGLOBAL g, char *ps, uint z)
p = GetCharString(buf);
strncpy(ps, p, z);
-} // end of Print
+} // end of Prints
/* -------------------------- Class TYPVAL ---------------------------- */
@@ -1349,7 +1350,7 @@ bool TYPVAL::SetValue_pval(PVAL valp, bool chktype)
char buf[64];
- if (!(Null = valp->IsNull() && Nullable))
+ if (!(Null = (valp->IsNull() && Nullable)))
strncpy(Strp, valp->GetCharString(buf), Len);
else
Reset();
@@ -1451,7 +1452,7 @@ void TYPVAL::SetValue(uint n)
if (k > Len) {
sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
+ throw 138;
} else
SetValue_psz(buf);
@@ -1505,7 +1506,7 @@ void TYPVAL::SetValue(ulonglong n)
if (k > Len) {
sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
+ throw 138;
} else
SetValue_psz(buf);
@@ -1655,32 +1656,36 @@ bool TYPVAL::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
int i;
for (i = 0; i < np; i++)
- p[i] = vp[i]->GetCharString(val[i]);
+ p[i] = vp[i]->IsNull() ? NULL : vp[i]->GetCharString(val[i]);
- switch (op) {
- case OP_CNC:
- assert(np == 1 || np == 2);
+ if (p[i-1]) {
+ switch (op) {
+ case OP_CNC:
+ assert(np == 1 || np == 2);
- if (np == 2)
- SetValue_psz(p[0]);
+ if (np == 2)
+ SetValue_psz(p[0]);
- if ((i = Len - (signed)strlen(Strp)) > 0)
- strncat(Strp, p[np - 1], i);
+ if ((i = Len - (signed)strlen(Strp)) > 0)
+ strncat(Strp, p[np - 1], i);
- break;
- case OP_MIN:
- assert(np == 2);
- SetValue_psz((strcmp(p[0], p[1]) < 0) ? p[0] : p[1]);
- break;
- case OP_MAX:
- assert(np == 2);
- SetValue_psz((strcmp(p[0], p[1]) > 0) ? p[0] : p[1]);
- break;
- default:
-// sprintf(g->Message, MSG(BAD_EXP_OPER), op);
- strcpy(g->Message, "Function not supported");
- return true;
- } // endswitch op
+ break;
+ case OP_MIN:
+ assert(np == 2);
+ SetValue_psz((strcmp(p[0], p[1]) < 0) ? p[0] : p[1]);
+ break;
+ case OP_MAX:
+ assert(np == 2);
+ SetValue_psz((strcmp(p[0], p[1]) > 0) ? p[0] : p[1]);
+ break;
+ default:
+ // sprintf(g->Message, MSG(BAD_EXP_OPER), op);
+ strcpy(g->Message, "Function not supported");
+ return true;
+ } // endswitch op
+
+ Null = false;
+ } // endif p[i]
return false;
} // end of Compute
@@ -1719,10 +1724,14 @@ void TYPVAL::Prints(PGLOBAL g, char *ps, uint z)
else
strcat(strncat(strncpy(ps, "\"", z), Strp, z-2), "\"");
-} // end of Print
+} // end of Prints
/* -------------------------- Class DECIMAL -------------------------- */
+/***********************************************************************/
+/* DECIMAL public constructor from a constant string. */
+/* -------------------------- Class DECIMAL -------------------------- */
+
/***********************************************************************/
/* DECIMAL public constructor from a constant string. */
/***********************************************************************/
@@ -2562,7 +2571,7 @@ bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
} else if (valp->GetType() == TYPE_BIGINT &&
!(valp->GetBigintValue() % 1000)) {
// Assuming that this timestamp is in milliseconds
- Tval = valp->GetBigintValue() / 1000;
+ Tval = (int)(valp->GetBigintValue() / 1000);
} else
Tval = valp->GetIntValue();
diff --git a/storage/connect/value.h b/storage/connect/value.h
index 2754c761815..f771d33dc52 100644
--- a/storage/connect/value.h
+++ b/storage/connect/value.h
@@ -90,8 +90,8 @@ class DllExport VALUE : public BLOCK {
virtual double GetFloatValue(void) = 0;
virtual void *GetTo_Val(void) = 0;
virtual void SetPrec(int prec) {Prec = prec;}
- bool IsNull(void) {return Null;}
- void SetNull(bool b) {Null = b;}
+ bool IsNull(void) {return (Nullable && Null);}
+ void SetNull(bool b) {Null = (Nullable ? b : false);}
bool GetNullable(void) {return Nullable;}
void SetNullable(bool b) {Nullable = b;}
int GetType(void) {return Type;}
diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp
index 3e4db8080ae..30dce3b7fef 100755
--- a/storage/connect/xindex.cpp
+++ b/storage/connect/xindex.cpp
@@ -188,7 +188,7 @@ void XXBASE::Printf(PGLOBAL, FILE *f, uint n)
memset(m, ' ', n); // Make margin string
m[n] = '\0';
fprintf(f, "%sXINDEX: Tbxp=%p Num=%d\n", m, Tbxp, Num_K);
- } // end of Print
+ } // end of Printf
/***********************************************************************/
/* Make string output of XINDEX contents. */
@@ -197,7 +197,7 @@ void XXBASE::Prints(PGLOBAL, char *ps, uint z)
{
*ps = '\0';
strncat(ps, "Xindex", z);
- } // end of Print
+ } // end of Prints
/* -------------------------- XINDEX Class --------------------------- */
@@ -3008,7 +3008,8 @@ KXYCOL::KXYCOL(PKXBASE kp) : To_Keys(Keys.Memp),
/***********************************************************************/
bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
{
- int len = colp->GetLength(), prec = colp->GetScale();
+ int len = colp->GetLength(), prec = colp->GetScale();
+ bool un = colp->IsUnsigned();
// Currently no indexing on NULL columns
if (colp->IsNullable() && kln) {
@@ -3028,7 +3029,7 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
// Allocate the Value object used when moving items
Type = colp->GetResultType();
- if (!(Valp = AllocateValue(g, Type, len, prec, colp->IsUnsigned())))
+ if (!(Valp = AllocateValue(g, Type, len, prec, un)))
return true;
Klen = Valp->GetClen();
@@ -3044,7 +3045,7 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
// Currently we set it to true to be compatible with QRY blocks,
// and the one before last is to enable length/type checking, set to
// true if not a prefix key.
- Kblp = AllocValBlock(g, To_Keys, Type, n, len, prec, !Prefix, true);
+ Kblp = AllocValBlock(g, To_Keys, Type, n, len, prec, !Prefix, true, un);
Asc = sm; // Sort mode: Asc=true Desc=false
Ndf = n;
@@ -3064,7 +3065,8 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
/***********************************************************************/
BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
{
- int len = colp->GetLength(), prec = colp->GetScale();
+ int len = colp->GetLength(), prec = colp->GetScale();
+ bool un = colp->IsUnsigned();
if (n[3] && colp->GetLength() > n[3]
&& colp->GetResultType() == TYPE_STRING) {
@@ -3079,7 +3081,7 @@ BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
this, colp, Type, n[0], len, m);
// Allocate the Value object used when moving items
- Valp = AllocateValue(g, Type, len, prec, colp->IsUnsigned());
+ Valp = AllocateValue(g, Type, len, prec, un);
Klen = Valp->GetClen();
if (n[2]) {
@@ -3088,7 +3090,7 @@ BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
Bkeys.Sub = true;
// Allocate the Valblk containing initial block key values
- Blkp = AllocValBlock(g, To_Bkeys, Type, n[2], len, prec, true, true);
+ Blkp = AllocValBlock(g, To_Bkeys, Type, n[2], len, prec, true, true, un);
} // endif nb
Keys.Size = n[0] * Klen;
@@ -3099,7 +3101,7 @@ BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
// by blanks (if true) or keep the zero ending char (if false).
// Currently we set it to true to be compatible with QRY blocks,
// and last one to enable type checking (no conversion).
- Kblp = AllocValBlock(g, To_Keys, Type, n[0], len, prec, !Prefix, true);
+ Kblp = AllocValBlock(g, To_Keys, Type, n[0], len, prec, !Prefix, true, un);
if (n[1]) {
Koff.Size = n[1] * sizeof(int);
diff --git a/storage/connect/xobject.cpp b/storage/connect/xobject.cpp
index 205edc12d0c..02d3e974dcc 100644
--- a/storage/connect/xobject.cpp
+++ b/storage/connect/xobject.cpp
@@ -84,7 +84,7 @@ double XOBJECT::GetFloatValue(void)
CONSTANT::CONSTANT(PGLOBAL g, void *value, short type)
{
if (!(Value = AllocateValue(g, value, (int)type)))
- throw TYPE_CONST;
+ throw (int)TYPE_CONST;
Constant = true;
} // end of CONSTANT constructor
@@ -95,7 +95,7 @@ CONSTANT::CONSTANT(PGLOBAL g, void *value, short type)
CONSTANT::CONSTANT(PGLOBAL g, int n)
{
if (!(Value = AllocateValue(g, &n, TYPE_INT)))
- throw TYPE_CONST;
+ throw (int)TYPE_CONST;
Constant = true;
} // end of CONSTANT constructor
@@ -117,7 +117,7 @@ void CONSTANT::Convert(PGLOBAL g, int newtype)
{
if (Value->GetType() != newtype)
if (!(Value = AllocateValue(g, Value, newtype)))
- throw TYPE_CONST;
+ throw (int)TYPE_CONST;
} // end of Convert
@@ -176,7 +176,7 @@ bool CONSTANT::Rephrase(PGLOBAL g, PSZ work)
void CONSTANT::Printf(PGLOBAL g, FILE *f, uint n)
{
Value->Printf(g, f, n);
- } /* end of Print */
+ } /* end of Printf */
/***********************************************************************/
/* Make string output of a constant object. */
@@ -184,7 +184,7 @@ void CONSTANT::Printf(PGLOBAL g, FILE *f, uint n)
void CONSTANT::Prints(PGLOBAL g, char *ps, uint z)
{
Value->Prints(g, ps, z);
- } /* end of Print */
+ } /* end of Prints */
/* -------------------------- Class STRING --------------------------- */
From 04ae1207edec4cac80d7206377ae22a8447aa08f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Wed, 2 Aug 2017 12:11:06 +0300
Subject: [PATCH 093/101] 5.6.36-82.1
---
storage/xtradb/buf/buf0flu.cc | 17 +++++++++++++++--
storage/xtradb/include/univ.i | 2 +-
storage/xtradb/log/log0log.cc | 2 ++
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc
index 36e24fb3a1b..d401439a98f 100644
--- a/storage/xtradb/buf/buf0flu.cc
+++ b/storage/xtradb/buf/buf0flu.cc
@@ -2789,7 +2789,10 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
when SRV_SHUTDOWN_CLEANUP is set other threads like the master
and the purge threads may be working as well. We start flushing
the buffer pool but can't be sure that no new pages are being
- dirtied until we enter SRV_SHUTDOWN_FLUSH_PHASE phase. */
+ dirtied until we enter SRV_SHUTDOWN_FLUSH_PHASE phase. Because
+ the LRU manager thread is also flushing at SRV_SHUTDOWN_CLEANUP
+ but not SRV_SHUTDOWN_FLUSH_PHASE, we only leave the
+ SRV_SHUTDOWN_CLEANUP loop when the LRU manager quits. */
do {
n_flushed = page_cleaner_do_flush_batch(PCT_IO(100), LSN_MAX);
@@ -2798,7 +2801,10 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
if (n_flushed == 0) {
os_thread_sleep(100000);
}
- } while (srv_shutdown_state == SRV_SHUTDOWN_CLEANUP);
+
+ os_rmb;
+ } while (srv_shutdown_state == SRV_SHUTDOWN_CLEANUP
+ || buf_lru_manager_is_active);
/* At this point all threads including the master and the purge
thread must have been suspended. */
@@ -2815,6 +2821,11 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
buf_flush_wait_LRU_batch_end();
+#ifdef UNIV_DEBUG
+ os_rmb;
+ ut_ad(!buf_lru_manager_is_active);
+#endif
+
bool success;
do {
@@ -2877,6 +2888,7 @@ DECLARE_THREAD(buf_flush_lru_manager_thread)(
#endif /* UNIV_DEBUG_THREAD_CREATION */
buf_lru_manager_is_active = true;
+ os_wmb;
/* On server shutdown, the LRU manager thread runs through cleanup
phase to provide free pages for the master and purge threads. */
@@ -2895,6 +2907,7 @@ DECLARE_THREAD(buf_flush_lru_manager_thread)(
}
buf_lru_manager_is_active = false;
+ os_wmb;
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index b4ad030a565..beaef2a2272 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -47,7 +47,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_BUGFIX MYSQL_VERSION_PATCH
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 82.0
+#define PERCONA_INNODB_VERSION 82.1
#endif
/* Enable UNIV_LOG_ARCHIVE in XtraDB */
diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc
index f73d5b458d1..7be7b2c3c5a 100644
--- a/storage/xtradb/log/log0log.cc
+++ b/storage/xtradb/log/log0log.cc
@@ -3499,6 +3499,7 @@ loop:
before proceeding further. */
srv_shutdown_state = SRV_SHUTDOWN_FLUSH_PHASE;
count = 0;
+ os_rmb;
while (buf_page_cleaner_is_active || buf_lru_manager_is_active) {
if (srv_print_verbose_log && count == 0) {
ib_logf(IB_LOG_LEVEL_INFO,
@@ -3510,6 +3511,7 @@ loop:
if (count > 600) {
count = 0;
}
+ os_rmb;
}
mutex_enter(&log_sys->mutex);
From b1a2031ff96f132bf065d6b41593a842478a6659 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Wed, 2 Aug 2017 12:17:21 +0300
Subject: [PATCH 094/101] 5.6.36-82.1
---
storage/tokudb/CMakeLists.txt | 2 +-
storage/tokudb/PerconaFT/CMakeLists.txt | 10 +
.../tokudb/PerconaFT/buildheader/make_tdb.cc | 5 +-
.../cmake_modules/TokuThirdParty.cmake | 3 +
.../PerconaFT/ft/cachetable/cachetable.cc | 9 +-
.../PerconaFT/ft/cachetable/cachetable.h | 3 +
storage/tokudb/PerconaFT/ft/ft-ops.cc | 97 +-
storage/tokudb/PerconaFT/ft/ft.cc | 3 +-
storage/tokudb/PerconaFT/ft/node.cc | 19 +-
storage/tokudb/PerconaFT/ft/node.h | 20 +-
.../PerconaFT/ft/serialize/ft-serialize.cc | 43 +-
.../PerconaFT/ft/serialize/ft-serialize.h | 23 +-
.../ft/serialize/ft_node-serialize.cc | 689 ++-
.../ft/serialize/ft_node-serialize.h | 67 +-
storage/tokudb/PerconaFT/ft/txn/roll.cc | 2 +-
storage/tokudb/PerconaFT/ft/txn/txn.cc | 9 +-
storage/tokudb/PerconaFT/ft/txn/txn.h | 5 +-
.../tokudb/PerconaFT/locktree/lock_request.cc | 152 +-
.../tokudb/PerconaFT/locktree/lock_request.h | 23 +-
storage/tokudb/PerconaFT/locktree/locktree.cc | 42 +-
storage/tokudb/PerconaFT/locktree/locktree.h | 37 +-
storage/tokudb/PerconaFT/locktree/manager.cc | 13 +
.../PerconaFT/locktree/tests/kill_waiter.cc | 100 +
.../locktree/tests/lock_request_killed.cc | 3 +-
.../locktree/tests/lock_request_not_killed.cc | 1 -
.../tests/lock_request_start_release_wait.cc | 91 +
.../tests/lock_request_start_retry_race.cc | 109 +-
.../tests/lock_request_start_retry_race_3.cc | 133 +
.../lock_request_start_retry_wait_race_2.cc | 135 +
.../PerconaFT/portability/toku_debug_sync.h | 77 +
.../PerconaFT/portability/toku_portability.h | 3 +
.../tests/test_iterate_live_transactions.cc | 9 +-
.../PerconaFT/src/tests/test_stress0.cc | 3 +-
.../src/tests/transactional_fileops.cc | 9 +
storage/tokudb/PerconaFT/src/ydb.cc | 40 +-
storage/tokudb/PerconaFT/src/ydb_row_lock.cc | 22 +-
storage/tokudb/PerconaFT/src/ydb_txn.cc | 8 +-
storage/tokudb/PerconaFT/tools/CMakeLists.txt | 8 +
storage/tokudb/PerconaFT/tools/ftverify.cc | 2 +-
storage/tokudb/PerconaFT/tools/tokuftdump.cc | 3 +-
storage/tokudb/ha_tokudb.cc | 124 +-
storage/tokudb/ha_tokudb.h | 41 +-
storage/tokudb/hatoku_hton.cc | 8 +
.../tokudb/r/kill_query_blocked_in_lt.result | 26 +
.../tokudb/r/locks-select-update-3.result | 5 +-
.../tokudb/t/kill_query_blocked_in_lt.test | 56 +
.../tokudb/t/locks-select-update-3.test | 10 +-
.../tokudb_backup/r/rpl_safe_slave.result | 2 -
.../tokudb_backup/t/rpl_safe_slave.inc | 3 -
.../rpl_tokudb_row_img_general_loop.inc | 42 +
.../tokudb_rpl/r/rpl_not_null_tokudb.result | 32 +-
.../tokudb_rpl/r/rpl_row_basic_3tokudb.result | 40 +-
.../r/rpl_tokudb_commit_after_flush.result | 15 +
.../tokudb_rpl/r/rpl_tokudb_insert_id.result | 554 ++
.../r/rpl_tokudb_insert_id_pk.result | 82 +
.../r/rpl_tokudb_multi_update.result | 29 +
.../r/rpl_tokudb_multi_update2.result | 60 +
.../r/rpl_tokudb_multi_update3.result | 202 +
.../r/rpl_tokudb_row_crash_safe.result | 2183 ++++++++
.../r/rpl_tokudb_row_img_blobs.result | 4739 +++++++++++++++++
.../r/rpl_tokudb_row_img_eng_full.result | 3681 +++++++++++++
.../r/rpl_tokudb_row_img_eng_min.result | 3522 ++++++++++++
.../r/rpl_tokudb_row_img_eng_noblob.result | 3522 ++++++++++++
.../r/rpl_tokudb_row_img_idx_full.result | 3505 ++++++++++++
.../r/rpl_tokudb_row_img_idx_min.result | 3530 ++++++++++++
.../r/rpl_tokudb_row_img_idx_noblob.result | 3530 ++++++++++++
.../tokudb_rpl/r/rpl_tokudb_row_log.result | 275 +
...l_tokudb_row_lower_case_table_names.result | 51 +
.../tokudb_rpl/r/rpl_tokudb_row_sp003.result | 60 +
.../tokudb_rpl/r/rpl_tokudb_row_sp006.result | 47 +
.../r/rpl_tokudb_row_trig004.result | 32 +
.../tokudb_rpl/r/rpl_tokudb_stm_log.result | 274 +
.../r/rpl_tokudb_stm_mixed_crash_safe.result | 1773 ++++++
...db_stm_mixed_lower_case_table_names.result | 48 +
.../tokudb_rpl/t/rpl_not_null_tokudb.test | 4 +-
.../tokudb_rpl/t/rpl_row_basic_3tokudb.test | 12 +-
.../t/rpl_tokudb_commit_after_flush.test | 6 +
.../t/rpl_tokudb_insert_id-master.opt | 1 +
.../t/rpl_tokudb_insert_id-slave.opt | 1 +
.../tokudb_rpl/t/rpl_tokudb_insert_id.test | 7 +
.../tokudb_rpl/t/rpl_tokudb_insert_id_pk.test | 7 +
.../tokudb_rpl/t/rpl_tokudb_multi_update.test | 4 +
.../t/rpl_tokudb_multi_update2-slave.opt | 1 +
.../t/rpl_tokudb_multi_update2.test | 14 +
.../t/rpl_tokudb_multi_update3.test | 13 +
.../t/rpl_tokudb_row_crash_safe-master.opt | 1 +
.../t/rpl_tokudb_row_crash_safe-slave.opt | 1 +
.../t/rpl_tokudb_row_crash_safe.test | 19 +
.../tokudb_rpl/t/rpl_tokudb_row_img_blobs.cnf | 1 +
.../t/rpl_tokudb_row_img_blobs.test | 53 +
.../t/rpl_tokudb_row_img_eng_full.cnf | 1 +
.../t/rpl_tokudb_row_img_eng_full.test | 50 +
.../t/rpl_tokudb_row_img_eng_min.cnf | 1 +
.../t/rpl_tokudb_row_img_eng_min.test | 42 +
.../t/rpl_tokudb_row_img_eng_noblob.cnf | 1 +
.../t/rpl_tokudb_row_img_eng_noblob.test | 42 +
.../t/rpl_tokudb_row_img_idx_full.cnf | 1 +
.../t/rpl_tokudb_row_img_idx_full.test | 38 +
.../t/rpl_tokudb_row_img_idx_min.cnf | 1 +
.../t/rpl_tokudb_row_img_idx_min.test | 41 +
.../t/rpl_tokudb_row_img_idx_noblob.cnf | 1 +
.../t/rpl_tokudb_row_img_idx_noblob.test | 41 +
.../t/rpl_tokudb_row_log-master.opt | 2 +
.../tokudb_rpl/t/rpl_tokudb_row_log.test | 15 +
...okudb_row_lower_case_table_names-slave.opt | 1 +
...rpl_tokudb_row_lower_case_table_names.test | 14 +
.../tokudb_rpl/t/rpl_tokudb_row_sp003.test | 14 +
.../tokudb_rpl/t/rpl_tokudb_row_sp006.test | 14 +
.../tokudb_rpl/t/rpl_tokudb_row_trig004.test | 19 +
.../t/rpl_tokudb_stm_log-master.opt | 2 +
.../tokudb_rpl/t/rpl_tokudb_stm_log.test | 15 +
...rpl_tokudb_stm_mixed_crash_safe-master.opt | 1 +
.../rpl_tokudb_stm_mixed_crash_safe-slave.opt | 1 +
.../t/rpl_tokudb_stm_mixed_crash_safe.test | 18 +
...stm_mixed_lower_case_table_names-slave.opt | 1 +
...kudb_stm_mixed_lower_case_table_names.test | 14 +
storage/tokudb/tokudb_information_schema.cc | 6 +-
storage/tokudb/tokudb_txn.h | 2 +-
118 files changed, 34162 insertions(+), 517 deletions(-)
create mode 100644 storage/tokudb/PerconaFT/locktree/tests/kill_waiter.cc
create mode 100644 storage/tokudb/PerconaFT/locktree/tests/lock_request_start_release_wait.cc
create mode 100644 storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_race_3.cc
create mode 100644 storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_wait_race_2.cc
create mode 100644 storage/tokudb/PerconaFT/portability/toku_debug_sync.h
create mode 100644 storage/tokudb/mysql-test/tokudb/r/kill_query_blocked_in_lt.result
create mode 100644 storage/tokudb/mysql-test/tokudb/t/kill_query_blocked_in_lt.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/include/rpl_tokudb_row_img_general_loop.inc
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_commit_after_flush.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id_pk.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update2.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update3.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_crash_safe.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_blobs.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_full.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_min.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_noblob.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_full.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_min.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_noblob.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_log.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_lower_case_table_names.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp003.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp006.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_trig004.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_log.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_crash_safe.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_lower_case_table_names.result
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_commit_after_flush.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-master.opt
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-slave.opt
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id_pk.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2-slave.opt
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update3.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-master.opt
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-slave.opt
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.cnf
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.cnf
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.cnf
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.cnf
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.cnf
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.cnf
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.cnf
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log-master.opt
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names-slave.opt
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp003.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp006.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_trig004.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log-master.opt
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-master.opt
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-slave.opt
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe.test
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names-slave.opt
create mode 100644 storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names.test
diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt
index 2438b7ac3fe..904dd9bbe4e 100644
--- a/storage/tokudb/CMakeLists.txt
+++ b/storage/tokudb/CMakeLists.txt
@@ -1,4 +1,4 @@
-SET(TOKUDB_VERSION 5.6.36-82.0)
+SET(TOKUDB_VERSION 5.6.36-82.1)
# PerconaFT only supports x86-64 and cmake-2.8.9+
IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND
NOT CMAKE_VERSION VERSION_LESS "2.8.9")
diff --git a/storage/tokudb/PerconaFT/CMakeLists.txt b/storage/tokudb/PerconaFT/CMakeLists.txt
index 59e0d145ce0..a850400e726 100644
--- a/storage/tokudb/PerconaFT/CMakeLists.txt
+++ b/storage/tokudb/PerconaFT/CMakeLists.txt
@@ -9,6 +9,16 @@ project(TokuDB)
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
+# detect when we are being built as a subproject
+if (DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
+ add_definitions( -DMYSQL_TOKUDB_ENGINE=1)
+ if ((CMAKE_BUILD_TYPE MATCHES "Debug") AND
+ (CMAKE_CXX_FLAGS_DEBUG MATCHES " -DENABLED_DEBUG_SYNC"))
+ include_directories(${CMAKE_SOURCE_DIR}/include)
+ include_directories(${CMAKE_SOURCE_DIR}/sql)
+ endif ()
+endif ()
+
## Versions of gcc >= 4.9.0 require special version of 'ar' and 'ranlib' for
## link-time optimizations to work properly.
##
diff --git a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc
index d0404b420f4..0a59da8a54c 100644
--- a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc
+++ b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc
@@ -428,6 +428,7 @@ static void print_db_env_struct (void) {
"int (*dirtool_attach)(DB_ENV *, DB_TXN *, const char *, const char *)",
"int (*dirtool_detach)(DB_ENV *, DB_TXN *, const char *)",
"int (*dirtool_move)(DB_ENV *, DB_TXN *, const char *, const char *)",
+ "void (*kill_waiter)(DB_ENV *, void *extra)",
NULL};
sort_and_dump_fields("db_env", true, extra);
@@ -548,8 +549,8 @@ static void print_db_txn_struct (void) {
"int (*abort_with_progress)(DB_TXN*, TXN_PROGRESS_POLL_FUNCTION, void*)",
"int (*xa_prepare) (DB_TXN*, TOKU_XA_XID *, uint32_t flags)",
"uint64_t (*id64) (DB_TXN*)",
- "void (*set_client_id)(DB_TXN *, uint64_t client_id)",
- "uint64_t (*get_client_id)(DB_TXN *)",
+ "void (*set_client_id)(DB_TXN *, uint64_t client_id, void *client_extra)",
+ "void (*get_client_id)(DB_TXN *, uint64_t *client_id, void **client_extra)",
"bool (*is_prepared)(DB_TXN *)",
"DB_TXN *(*get_child)(DB_TXN *)",
"uint64_t (*get_start_time)(DB_TXN *)",
diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuThirdParty.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuThirdParty.cmake
index db94b19f08c..b707f368431 100644
--- a/storage/tokudb/PerconaFT/cmake_modules/TokuThirdParty.cmake
+++ b/storage/tokudb/PerconaFT/cmake_modules/TokuThirdParty.cmake
@@ -123,6 +123,9 @@ ExternalProject_Add(build_snappy
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
+ -DCMAKE_AR=${CMAKE_AR}
+ -DCMAKE_NM=${CMAKE_NM}
+ -DCMAKE_RANLIB=${CMAKE_RANLIB}
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
${USE_PROJECT_CMAKE_MODULE_PATH}
diff --git a/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc b/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc
index 6d753805fa9..31aab932fd6 100644
--- a/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc
+++ b/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc
@@ -464,7 +464,10 @@ int toku_cachetable_openf (CACHEFILE *cfptr, CACHETABLE ct, const char *fname_in
char *
toku_cachefile_fname_in_env (CACHEFILE cf) {
- return cf->fname_in_env;
+ if (cf) {
+ return cf->fname_in_env;
+ }
+ return nullptr;
}
void toku_cachefile_set_fname_in_env(CACHEFILE cf, char *new_fname_in_env) {
@@ -2890,6 +2893,10 @@ toku_cachefile_get_cachetable(CACHEFILE cf) {
return cf->cachetable;
}
+CACHEFILE toku_pair_get_cachefile(PAIR pair) {
+ return pair->cachefile;
+}
+
//Only called by ft_end_checkpoint
//Must have access to cf->fd (must be protected)
void toku_cachefile_fsync(CACHEFILE cf) {
diff --git a/storage/tokudb/PerconaFT/ft/cachetable/cachetable.h b/storage/tokudb/PerconaFT/ft/cachetable/cachetable.h
index 3b3cb0a2d46..b9851f33e20 100644
--- a/storage/tokudb/PerconaFT/ft/cachetable/cachetable.h
+++ b/storage/tokudb/PerconaFT/ft/cachetable/cachetable.h
@@ -297,6 +297,9 @@ void *toku_cachefile_get_userdata(CACHEFILE);
CACHETABLE toku_cachefile_get_cachetable(CACHEFILE cf);
// Effect: Get the cachetable.
+CACHEFILE toku_pair_get_cachefile(PAIR);
+// Effect: Get the cachefile of the pair
+
void toku_cachetable_swap_pair_values(PAIR old_pair, PAIR new_pair);
// Effect: Swaps the value_data of old_pair and new_pair.
// Requires: both old_pair and new_pair to be pinned with write locks.
diff --git a/storage/tokudb/PerconaFT/ft/ft-ops.cc b/storage/tokudb/PerconaFT/ft/ft-ops.cc
index 63c6335dafd..07e244947e4 100644
--- a/storage/tokudb/PerconaFT/ft/ft-ops.cc
+++ b/storage/tokudb/PerconaFT/ft/ft-ops.cc
@@ -651,8 +651,12 @@ void toku_ftnode_clone_callback(void *value_data,
// set new pair attr if necessary
if (node->height == 0) {
*new_attr = make_ftnode_pair_attr(node);
- node->logical_rows_delta = 0;
- cloned_node->logical_rows_delta = 0;
+ for (int i = 0; i < node->n_children; i++) {
+ if (BP_STATE(node, i) == PT_AVAIL) {
+ BLB_LRD(node, i) = 0;
+ BLB_LRD(cloned_node, i) = 0;
+ }
+ }
} else {
new_attr->is_valid = false;
}
@@ -700,9 +704,26 @@ void toku_ftnode_flush_callback(CACHEFILE UU(cachefile),
if (ftnode->height == 0) {
FT_STATUS_INC(FT_FULL_EVICTIONS_LEAF, 1);
FT_STATUS_INC(FT_FULL_EVICTIONS_LEAF_BYTES, node_size);
- if (!ftnode->dirty) {
- toku_ft_adjust_logical_row_count(
- ft, -ftnode->logical_rows_delta);
+
+ // A leaf node (height == 0) is being evicted (!keep_me) and is
+ // not a checkpoint clone (!is_clone). This leaf node may have
+ // had messages applied to satisfy a query, but was never
+ // actually dirtied (!ftnode->dirty && !write_me). **Note that
+ // if (write_me) would persist the node and clear the dirty
+ // flag **. This message application may have updated the trees
+ // logical row count. Since these message applications are not
+ // persisted, we need undo the logical row count adjustments as
+ // they may occur again in the future if/when the node is
+ // re-read from disk for another query or change.
+ if (!ftnode->dirty && !write_me) {
+ int64_t lrc_delta = 0;
+ for (int i = 0; i < ftnode->n_children; i++) {
+ if (BP_STATE(ftnode, i) == PT_AVAIL) {
+ lrc_delta -= BLB_LRD(ftnode, i);
+ BLB_LRD(ftnode, i) = 0;
+ }
+ }
+ toku_ft_adjust_logical_row_count(ft, lrc_delta);
}
} else {
FT_STATUS_INC(FT_FULL_EVICTIONS_NONLEAF, 1);
@@ -711,6 +732,11 @@ void toku_ftnode_flush_callback(CACHEFILE UU(cachefile),
toku_free(*disk_data);
} else {
if (ftnode->height == 0) {
+ // No need to adjust logical row counts when flushing a clone
+ // as they should have been zeroed out anyway when cloned.
+ // Clones are 'copies' of work already done so doing it again
+ // (adjusting row counts) would be redundant and leads to
+ // inaccurate counts.
for (int i = 0; i < ftnode->n_children; i++) {
if (BP_STATE(ftnode, i) == PT_AVAIL) {
BASEMENTNODE bn = BLB(ftnode, i);
@@ -718,10 +744,6 @@ void toku_ftnode_flush_callback(CACHEFILE UU(cachefile),
bn->stat64_delta);
}
}
- if (!ftnode->dirty) {
- toku_ft_adjust_logical_row_count(
- ft, -ftnode->logical_rows_delta);
- }
}
}
toku_ftnode_free(&ftnode);
@@ -748,24 +770,48 @@ toku_ft_status_update_pivot_fetch_reason(ftnode_fetch_extra *bfe)
}
}
-int toku_ftnode_fetch_callback (CACHEFILE UU(cachefile), PAIR p, int fd, BLOCKNUM blocknum, uint32_t fullhash,
- void **ftnode_pv, void** disk_data, PAIR_ATTR *sizep, int *dirtyp, void *extraargs) {
+int toku_ftnode_fetch_callback(CACHEFILE UU(cachefile),
+ PAIR p,
+ int fd,
+ BLOCKNUM blocknum,
+ uint32_t fullhash,
+ void **ftnode_pv,
+ void **disk_data,
+ PAIR_ATTR *sizep,
+ int *dirtyp,
+ void *extraargs) {
assert(extraargs);
- assert(*ftnode_pv == NULL);
- FTNODE_DISK_DATA* ndd = (FTNODE_DISK_DATA*)disk_data;
+ assert(*ftnode_pv == nullptr);
+ FTNODE_DISK_DATA *ndd = (FTNODE_DISK_DATA *)disk_data;
ftnode_fetch_extra *bfe = (ftnode_fetch_extra *)extraargs;
- FTNODE *node=(FTNODE*)ftnode_pv;
+ FTNODE *node = (FTNODE *)ftnode_pv;
// deserialize the node, must pass the bfe in because we cannot
// evaluate what piece of the the node is necessary until we get it at
// least partially into memory
- int r = toku_deserialize_ftnode_from(fd, blocknum, fullhash, node, ndd, bfe);
+ int r =
+ toku_deserialize_ftnode_from(fd, blocknum, fullhash, node, ndd, bfe);
if (r != 0) {
if (r == TOKUDB_BAD_CHECKSUM) {
- fprintf(stderr,
- "Checksum failure while reading node in file %s.\n",
- toku_cachefile_fname_in_env(cachefile));
+ fprintf(
+ stderr,
+ "%s:%d:toku_ftnode_fetch_callback - "
+ "file[%s], blocknum[%ld], toku_deserialize_ftnode_from "
+ "failed with a checksum error.\n",
+ __FILE__,
+ __LINE__,
+ toku_cachefile_fname_in_env(cachefile),
+ blocknum.b);
} else {
- fprintf(stderr, "Error deserializing node, errno = %d", r);
+ fprintf(
+ stderr,
+ "%s:%d:toku_ftnode_fetch_callback - "
+ "file[%s], blocknum[%ld], toku_deserialize_ftnode_from "
+ "failed with %d.\n",
+ __FILE__,
+ __LINE__,
+ toku_cachefile_fname_in_env(cachefile),
+ blocknum.b,
+ r);
}
// make absolutely sure we crash before doing anything else.
abort();
@@ -774,7 +820,8 @@ int toku_ftnode_fetch_callback (CACHEFILE UU(cachefile), PAIR p, int fd, BLOCKNU
if (r == 0) {
*sizep = make_ftnode_pair_attr(*node);
(*node)->ct_pair = p;
- *dirtyp = (*node)->dirty; // deserialize could mark the node as dirty (presumably for upgrade)
+ *dirtyp = (*node)->dirty; // deserialize could mark the node as dirty
+ // (presumably for upgrade)
}
return r;
}
@@ -947,6 +994,16 @@ int toku_ftnode_pe_callback(void *ftnode_pv,
basements_to_destroy[num_basements_to_destroy++] = bn;
toku_ft_decrease_stats(&ft->in_memory_stats,
bn->stat64_delta);
+ // A basement node is being partially evicted.
+ // This masement node may have had messages applied to it to
+ // satisfy a query, but was never actually dirtied.
+ // This message application may have updated the trees
+ // logical row count. Since these message applications are
+ // not being persisted, we need undo the logical row count
+ // adjustments as they may occur again in the future if/when
+ // the node is re-read from disk for another query or change.
+ toku_ft_adjust_logical_row_count(ft,
+ -bn->logical_rows_delta);
set_BNULL(node, i);
BP_STATE(node, i) = PT_ON_DISK;
num_partial_evictions++;
diff --git a/storage/tokudb/PerconaFT/ft/ft.cc b/storage/tokudb/PerconaFT/ft/ft.cc
index 7c94b4c59d3..700e532d5cf 100644
--- a/storage/tokudb/PerconaFT/ft/ft.cc
+++ b/storage/tokudb/PerconaFT/ft/ft.cc
@@ -435,7 +435,8 @@ int toku_read_ft_and_store_in_cachefile (FT_HANDLE ft_handle, CACHEFILE cf, LSN
}
int fd = toku_cachefile_get_fd(cf);
- int r = toku_deserialize_ft_from(fd, max_acceptable_lsn, &ft);
+ const char *fn = toku_cachefile_fname_in_env(cf);
+ int r = toku_deserialize_ft_from(fd, fn, max_acceptable_lsn, &ft);
if (r == TOKUDB_BAD_CHECKSUM) {
fprintf(stderr, "Checksum failure while reading header in file %s.\n", toku_cachefile_fname_in_env(cf));
assert(false); // make absolutely sure we crash before doing anything else
diff --git a/storage/tokudb/PerconaFT/ft/node.cc b/storage/tokudb/PerconaFT/ft/node.cc
index 07309ff7f94..ce918940bd7 100644
--- a/storage/tokudb/PerconaFT/ft/node.cc
+++ b/storage/tokudb/PerconaFT/ft/node.cc
@@ -93,6 +93,7 @@ void toku_destroy_ftnode_internals(FTNODE node) {
if (node->height > 0) {
destroy_nonleaf_childinfo(BNC(node,i));
} else {
+ paranoid_invariant(BLB_LRD(node, i) == 0);
destroy_basement_node(BLB(node, i));
}
} else if (BP_STATE(node,i) == PT_COMPRESSED) {
@@ -386,8 +387,7 @@ static void bnc_apply_messages_to_basement_node(
const pivot_bounds &
bounds, // contains pivot key bounds of this basement node
txn_gc_info *gc_info,
- bool *msgs_applied,
- int64_t* logical_rows_delta) {
+ bool *msgs_applied) {
int r;
NONLEAF_CHILDINFO bnc = BNC(ancestor, childnum);
@@ -395,6 +395,7 @@ static void bnc_apply_messages_to_basement_node(
// apply messages from this buffer
STAT64INFO_S stats_delta = {0, 0};
uint64_t workdone_this_ancestor = 0;
+ int64_t logical_rows_delta = 0;
uint32_t stale_lbi, stale_ube;
if (!bn->stale_ancestor_messages_applied) {
@@ -470,7 +471,7 @@ static void bnc_apply_messages_to_basement_node(
gc_info,
&workdone_this_ancestor,
&stats_delta,
- logical_rows_delta);
+ &logical_rows_delta);
}
} else if (stale_lbi == stale_ube) {
// No stale messages to apply, we just apply fresh messages, and mark
@@ -482,7 +483,7 @@ static void bnc_apply_messages_to_basement_node(
.gc_info = gc_info,
.workdone = &workdone_this_ancestor,
.stats_to_update = &stats_delta,
- .logical_rows_delta = logical_rows_delta};
+ .logical_rows_delta = &logical_rows_delta};
if (fresh_ube - fresh_lbi > 0)
*msgs_applied = true;
r = bnc->fresh_message_tree
@@ -503,7 +504,7 @@ static void bnc_apply_messages_to_basement_node(
.gc_info = gc_info,
.workdone = &workdone_this_ancestor,
.stats_to_update = &stats_delta,
- .logical_rows_delta = logical_rows_delta};
+ .logical_rows_delta = &logical_rows_delta};
r = bnc->stale_message_tree
.iterate_on_rangeft->in_memory_stats, stats_delta);
}
+ toku_ft_adjust_logical_row_count(t->ft, logical_rows_delta);
+ bn->logical_rows_delta += logical_rows_delta;
}
static void
@@ -534,7 +537,6 @@ apply_ancestors_messages_to_bn(
bool* msgs_applied
)
{
- int64_t logical_rows_delta = 0;
BASEMENTNODE curr_bn = BLB(node, childnum);
const pivot_bounds curr_bounds = bounds.next_bounds(node, childnum);
for (ANCESTORS curr_ancestors = ancestors; curr_ancestors; curr_ancestors = curr_ancestors->next) {
@@ -547,16 +549,13 @@ apply_ancestors_messages_to_bn(
curr_ancestors->childnum,
curr_bounds,
gc_info,
- msgs_applied,
- &logical_rows_delta
+ msgs_applied
);
// We don't want to check this ancestor node again if the
// next time we query it, the msn hasn't changed.
curr_bn->max_msn_applied = curr_ancestors->node->max_msn_applied_to_node_on_disk;
}
}
- toku_ft_adjust_logical_row_count(t->ft, logical_rows_delta);
- node->logical_rows_delta += logical_rows_delta;
// At this point, we know all the stale messages above this
// basement node have been applied, and any new messages will be
// fresh, so we don't need to look at stale messages for this
diff --git a/storage/tokudb/PerconaFT/ft/node.h b/storage/tokudb/PerconaFT/ft/node.h
index db189e36d59..05c8a44ebed 100644
--- a/storage/tokudb/PerconaFT/ft/node.h
+++ b/storage/tokudb/PerconaFT/ft/node.h
@@ -175,11 +175,6 @@ struct ftnode {
int height;
int dirty;
uint32_t fullhash;
- // current count of rows add or removed as a result of message application
- // to this node as a basement, irrelevant for internal nodes, gets reset
- // when node is undirtied. Used to back out tree scoped LRC id node is
- // evicted but not persisted
- int64_t logical_rows_delta;
// for internal nodes, if n_children==fanout+1 then the tree needs to be
// rebalanced. for leaf nodes, represents number of basement nodes
@@ -211,6 +206,10 @@ struct ftnode_leaf_basement_node {
unsigned int seqinsert; // number of sequential inserts to this leaf
MSN max_msn_applied; // max message sequence number applied
bool stale_ancestor_messages_applied;
+ // current count of rows added or removed as a result of message application
+ // to this basement node, gets reset when node is undirtied.
+ // Used to back out tree scoped LRC id node is evicted but not persisted
+ int64_t logical_rows_delta;
STAT64INFO_S stat64_delta; // change in stat64 counters since basement was last written to disk
};
typedef struct ftnode_leaf_basement_node *BASEMENTNODE;
@@ -385,6 +384,16 @@ enum reactivity toku_ftnode_get_reactivity(FT ft, FTNODE node);
enum reactivity toku_ftnode_get_nonleaf_reactivity(FTNODE node, unsigned int fanout);
enum reactivity toku_ftnode_get_leaf_reactivity(FTNODE node, uint32_t nodesize);
+inline const char* toku_ftnode_get_cachefile_fname_in_env(FTNODE node) {
+ if (node->ct_pair) {
+ CACHEFILE cf = toku_pair_get_cachefile(node->ct_pair);
+ if (cf) {
+ return toku_cachefile_fname_in_env(cf);
+ }
+ }
+ return nullptr;
+}
+
/**
* Finds the next child for HOT to flush to, given that everything up to
* and including k has been flattened.
@@ -577,3 +586,4 @@ static inline void set_BSB(FTNODE node, int i, struct sub_block *sb) {
#define BLB_DATA(node,i) (&(BLB(node,i)->data_buffer))
#define BLB_NBYTESINDATA(node,i) (BLB_DATA(node,i)->get_disk_size())
#define BLB_SEQINSERT(node,i) (BLB(node,i)->seqinsert)
+#define BLB_LRD(node, i) (BLB(node,i)->logical_rows_delta)
diff --git a/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc b/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc
index 8fcb5293412..fcab9fc675e 100644
--- a/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc
+++ b/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc
@@ -644,7 +644,29 @@ exit:
// Read ft from file into struct. Read both headers and use one.
// We want the latest acceptable header whose checkpoint_lsn is no later
// than max_acceptable_lsn.
-int toku_deserialize_ft_from(int fd, LSN max_acceptable_lsn, FT *ft) {
+#define dump_state_of_toku_deserialize_ft_from() \
+ fprintf(stderr, \
+ "%s:%d toku_deserialize_ft_from: " \
+ "filename[%s] " \
+ "r[%d] max_acceptable_lsn[%lu]" \
+ "r0[%d] checkpoint_lsn_0[%lu] checkpoint_count_0[%lu] " \
+ "r1[%d] checkpoint_lsn_1[%lu] checkpoint_count_1[%lu]\n", \
+ __FILE__, \
+ __LINE__, \
+ fn, \
+ r, \
+ max_acceptable_lsn.lsn, \
+ r0, \
+ checkpoint_lsn_0.lsn, \
+ checkpoint_count_0, \
+ r1, \
+ checkpoint_lsn_1.lsn, \
+ checkpoint_count_1);
+
+int toku_deserialize_ft_from(int fd,
+ const char *fn,
+ LSN max_acceptable_lsn,
+ FT *ft) {
struct rbuf rb_0;
struct rbuf rb_1;
uint64_t checkpoint_count_0 = 0;
@@ -655,7 +677,7 @@ int toku_deserialize_ft_from(int fd, LSN max_acceptable_lsn, FT *ft) {
bool h0_acceptable = false;
bool h1_acceptable = false;
struct rbuf *rb = NULL;
- int r0, r1, r;
+ int r0, r1, r = 0;
toku_off_t header_0_off = 0;
r0 = deserialize_ft_from_fd_into_rbuf(fd,
@@ -702,6 +724,10 @@ int toku_deserialize_ft_from(int fd, LSN max_acceptable_lsn, FT *ft) {
// first header, unless it's readable
}
+ if (r != TOKUDB_DICTIONARY_NO_HEADER) {
+ dump_state_of_toku_deserialize_ft_from();
+ }
+
// it should not be possible for both headers to be later than the
// max_acceptable_lsn
invariant(
@@ -713,11 +739,19 @@ int toku_deserialize_ft_from(int fd, LSN max_acceptable_lsn, FT *ft) {
if (h0_acceptable && h1_acceptable) {
if (checkpoint_count_0 > checkpoint_count_1) {
+ if (!(checkpoint_count_0 == checkpoint_count_1 + 1) ||
+ !(version_0 >= version_1)) {
+ dump_state_of_toku_deserialize_ft_from();
+ }
invariant(checkpoint_count_0 == checkpoint_count_1 + 1);
invariant(version_0 >= version_1);
rb = &rb_0;
version = version_0;
} else {
+ if (!(checkpoint_count_1 == checkpoint_count_0 + 1) ||
+ !(version_1 >= version_0)) {
+ dump_state_of_toku_deserialize_ft_from();
+ }
invariant(checkpoint_count_1 == checkpoint_count_0 + 1);
invariant(version_1 >= version_0);
rb = &rb_1;
@@ -729,6 +763,7 @@ int toku_deserialize_ft_from(int fd, LSN max_acceptable_lsn, FT *ft) {
fprintf(
stderr,
"Header 2 checksum failed, but header 1 ok. Proceeding.\n");
+ dump_state_of_toku_deserialize_ft_from();
}
rb = &rb_0;
version = version_0;
@@ -738,11 +773,15 @@ int toku_deserialize_ft_from(int fd, LSN max_acceptable_lsn, FT *ft) {
fprintf(
stderr,
"Header 1 checksum failed, but header 2 ok. Proceeding.\n");
+ dump_state_of_toku_deserialize_ft_from();
}
rb = &rb_1;
version = version_1;
}
+ if (!rb) {
+ dump_state_of_toku_deserialize_ft_from();
+ }
paranoid_invariant(rb);
r = deserialize_ft_versioned(fd, rb, ft, version);
diff --git a/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.h b/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.h
index fe31ff7c5fd..144e188566c 100644
--- a/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.h
+++ b/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.h
@@ -42,12 +42,23 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
#include "ft/serialize/block_table.h"
size_t toku_serialize_ft_size(struct ft_header *h);
-void toku_serialize_ft_to(int fd, struct ft_header *h, block_table *bt, CACHEFILE cf);
-void toku_serialize_ft_to_wbuf(struct wbuf *wbuf, struct ft_header *h, DISKOFF translation_location_on_disk, DISKOFF translation_size_on_disk);
-void toku_serialize_descriptor_contents_to_fd(int fd, DESCRIPTOR desc, DISKOFF offset);
-void toku_serialize_descriptor_contents_to_wbuf(struct wbuf *wb, DESCRIPTOR desc);
-
-int toku_deserialize_ft_from(int fd, LSN max_acceptable_lsn, FT *ft);
+void toku_serialize_ft_to(int fd,
+ struct ft_header *h,
+ block_table *bt,
+ CACHEFILE cf);
+void toku_serialize_ft_to_wbuf(struct wbuf *wbuf,
+ struct ft_header *h,
+ DISKOFF translation_location_on_disk,
+ DISKOFF translation_size_on_disk);
+void toku_serialize_descriptor_contents_to_fd(int fd,
+ DESCRIPTOR desc,
+ DISKOFF offset);
+void toku_serialize_descriptor_contents_to_wbuf(struct wbuf *wb,
+ DESCRIPTOR desc);
+int toku_deserialize_ft_from(int fd,
+ const char *fn,
+ LSN max_acceptable_lsn,
+ FT *ft);
// TODO rename
int deserialize_ft_from_fd_into_rbuf(int fd,
diff --git a/storage/tokudb/PerconaFT/ft/serialize/ft_node-serialize.cc b/storage/tokudb/PerconaFT/ft/serialize/ft_node-serialize.cc
index 56876b474d4..55899905baf 100644
--- a/storage/tokudb/PerconaFT/ft/serialize/ft_node-serialize.cc
+++ b/storage/tokudb/PerconaFT/ft/serialize/ft_node-serialize.cc
@@ -830,6 +830,13 @@ int toku_serialize_ftnode_to(int fd,
node->dirty = 0; // See #1957. Must set the node to be clean after
// serializing it so that it doesn't get written again on
// the next checkpoint or eviction.
+ if (node->height == 0) {
+ for (int i = 0; i < node->n_children; i++) {
+ if (BP_STATE(node, i) == PT_AVAIL) {
+ BLB_LRD(node, i) = 0;
+ }
+ }
+ }
return 0;
}
@@ -996,6 +1003,7 @@ BASEMENTNODE toku_clone_bn(BASEMENTNODE orig_bn) {
bn->seqinsert = orig_bn->seqinsert;
bn->stale_ancestor_messages_applied = orig_bn->stale_ancestor_messages_applied;
bn->stat64_delta = orig_bn->stat64_delta;
+ bn->logical_rows_delta = orig_bn->logical_rows_delta;
bn->data_buffer.clone(&orig_bn->data_buffer);
return bn;
}
@@ -1006,6 +1014,7 @@ BASEMENTNODE toku_create_empty_bn_no_buffer(void) {
bn->seqinsert = 0;
bn->stale_ancestor_messages_applied = false;
bn->stat64_delta = ZEROSTATS;
+ bn->logical_rows_delta = 0;
bn->data_buffer.init_zero();
return bn;
}
@@ -1149,15 +1158,25 @@ just_decompress_sub_block(struct sub_block *sb)
}
// verify the checksum
-int
-verify_ftnode_sub_block (struct sub_block *sb)
-{
+int verify_ftnode_sub_block(struct sub_block *sb,
+ const char *fname,
+ BLOCKNUM blocknum) {
int r = 0;
// first verify the checksum
uint32_t data_size = sb->uncompressed_size - 4; // checksum is 4 bytes at end
uint32_t stored_xsum = toku_dtoh32(*((uint32_t *)((char *)sb->uncompressed_ptr + data_size)));
uint32_t actual_xsum = toku_x1764_memory(sb->uncompressed_ptr, data_size);
if (stored_xsum != actual_xsum) {
+ fprintf(
+ stderr,
+ "%s:%d:verify_ftnode_sub_block - "
+ "file[%s], blocknum[%ld], stored_xsum[%u] != actual_xsum[%u]\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ stored_xsum,
+ actual_xsum);
dump_bad_block((Bytef *) sb->uncompressed_ptr, sb->uncompressed_size);
r = TOKUDB_BAD_CHECKSUM;
}
@@ -1165,19 +1184,27 @@ verify_ftnode_sub_block (struct sub_block *sb)
}
// This function deserializes the data stored by serialize_ftnode_info
-static int
-deserialize_ftnode_info(
- struct sub_block *sb,
- FTNODE node
- )
-{
+static int deserialize_ftnode_info(struct sub_block *sb, FTNODE node) {
+
// sb_node_info->uncompressed_ptr stores the serialized node information
// this function puts that information into node
// first verify the checksum
int r = 0;
- r = verify_ftnode_sub_block(sb);
+ const char *fname = toku_ftnode_get_cachefile_fname_in_env(node);
+ r = verify_ftnode_sub_block(sb, fname, node->blocknum);
if (r != 0) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_info - "
+ "file[%s], blocknum[%ld], verify_ftnode_sub_block failed with %d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ node->blocknum.b,
+ r);
+ dump_bad_block(static_cast(sb->uncompressed_ptr),
+ sb->uncompressed_size);
goto exit;
}
@@ -1223,6 +1250,16 @@ deserialize_ftnode_info(
// make sure that all the data was read
if (data_size != rb.ndone) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_info - "
+ "file[%s], blocknum[%ld], data_size[%d] != rb.ndone[%d]\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ node->blocknum.b,
+ data_size,
+ rb.ndone);
dump_bad_block(rb.buf, rb.size);
abort();
}
@@ -1339,17 +1376,25 @@ static void setup_ftnode_partitions(FTNODE node, ftnode_fetch_extra *bfe, bool d
/* deserialize the partition from the sub-block's uncompressed buffer
* and destroy the uncompressed buffer
*/
-static int
-deserialize_ftnode_partition(
+static int deserialize_ftnode_partition(
struct sub_block *sb,
FTNODE node,
- int childnum, // which partition to deserialize
- const toku::comparator &cmp
- )
-{
+ int childnum, // which partition to deserialize
+ const toku::comparator &cmp) {
+
int r = 0;
- r = verify_ftnode_sub_block(sb);
+ const char *fname = toku_ftnode_get_cachefile_fname_in_env(node);
+ r = verify_ftnode_sub_block(sb, fname, node->blocknum);
if (r != 0) {
+ fprintf(stderr,
+ "%s:%d:deserialize_ftnode_partition - "
+ "file[%s], blocknum[%ld], "
+ "verify_ftnode_sub_block failed with %d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ node->blocknum.b,
+ r);
goto exit;
}
uint32_t data_size;
@@ -1362,7 +1407,20 @@ deserialize_ftnode_partition(
ch = rbuf_char(&rb);
if (node->height > 0) {
- assert(ch == FTNODE_PARTITION_MSG_BUFFER);
+ if (ch != FTNODE_PARTITION_MSG_BUFFER) {
+ fprintf(stderr,
+ "%s:%d:deserialize_ftnode_partition - "
+ "file[%s], blocknum[%ld], ch[%d] != "
+ "FTNODE_PARTITION_MSG_BUFFER[%d]\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ node->blocknum.b,
+ ch,
+ FTNODE_PARTITION_MSG_BUFFER);
+ dump_bad_block(rb.buf, rb.size);
+ assert(ch == FTNODE_PARTITION_MSG_BUFFER);
+ }
NONLEAF_CHILDINFO bnc = BNC(node, childnum);
if (node->layout_version_read_from_disk <= FT_LAYOUT_VERSION_26) {
// Layout version <= 26 did not serialize sorted message trees to disk.
@@ -1371,43 +1429,99 @@ deserialize_ftnode_partition(
deserialize_child_buffer(bnc, &rb);
}
BP_WORKDONE(node, childnum) = 0;
- }
- else {
- assert(ch == FTNODE_PARTITION_DMT_LEAVES);
+ } else {
+ if (ch != FTNODE_PARTITION_DMT_LEAVES) {
+ fprintf(stderr,
+ "%s:%d:deserialize_ftnode_partition - "
+ "file[%s], blocknum[%ld], ch[%d] != "
+ "FTNODE_PARTITION_DMT_LEAVES[%d]\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ node->blocknum.b,
+ ch,
+ FTNODE_PARTITION_DMT_LEAVES);
+ dump_bad_block(rb.buf, rb.size);
+ assert(ch == FTNODE_PARTITION_DMT_LEAVES);
+ }
+
BLB_SEQINSERT(node, childnum) = 0;
uint32_t num_entries = rbuf_int(&rb);
// we are now at the first byte of first leafentry
data_size -= rb.ndone; // remaining bytes of leafentry data
BASEMENTNODE bn = BLB(node, childnum);
- bn->data_buffer.deserialize_from_rbuf(num_entries, &rb, data_size, node->layout_version_read_from_disk);
+ bn->data_buffer.deserialize_from_rbuf(
+ num_entries, &rb, data_size, node->layout_version_read_from_disk);
}
- assert(rb.ndone == rb.size);
+ if (rb.ndone != rb.size) {
+ fprintf(stderr,
+ "%s:%d:deserialize_ftnode_partition - "
+ "file[%s], blocknum[%ld], rb.ndone[%d] != rb.size[%d]\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ node->blocknum.b,
+ rb.ndone,
+ rb.size);
+ dump_bad_block(rb.buf, rb.size);
+ assert(rb.ndone == rb.size);
+ }
+
exit:
return r;
}
-static int
-decompress_and_deserialize_worker(struct rbuf curr_rbuf, struct sub_block curr_sb, FTNODE node, int child,
- const toku::comparator &cmp, tokutime_t *decompress_time)
-{
+static int decompress_and_deserialize_worker(struct rbuf curr_rbuf,
+ struct sub_block curr_sb,
+ FTNODE node,
+ int child,
+ const toku::comparator &cmp,
+ tokutime_t *decompress_time) {
int r = 0;
tokutime_t t0 = toku_time_now();
r = read_and_decompress_sub_block(&curr_rbuf, &curr_sb);
- tokutime_t t1 = toku_time_now();
- if (r == 0) {
- // at this point, sb->uncompressed_ptr stores the serialized node partition
- r = deserialize_ftnode_partition(&curr_sb, node, child, cmp);
+ if (r != 0) {
+ const char *fname = toku_ftnode_get_cachefile_fname_in_env(node);
+ fprintf(stderr,
+ "%s:%d:decompress_and_deserialize_worker - "
+ "file[%s], blocknum[%ld], read_and_decompress_sub_block failed "
+ "with %d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ node->blocknum.b,
+ r);
+ dump_bad_block(curr_rbuf.buf, curr_rbuf.size);
+ goto exit;
+ }
+ *decompress_time = toku_time_now() - t0;
+ // at this point, sb->uncompressed_ptr stores the serialized node partition
+ r = deserialize_ftnode_partition(&curr_sb, node, child, cmp);
+ if (r != 0) {
+ const char *fname = toku_ftnode_get_cachefile_fname_in_env(node);
+ fprintf(stderr,
+ "%s:%d:decompress_and_deserialize_worker - "
+ "file[%s], blocknum[%ld], deserialize_ftnode_partition failed "
+ "with %d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ node->blocknum.b,
+ r);
+ dump_bad_block(curr_rbuf.buf, curr_rbuf.size);
+ goto exit;
}
- *decompress_time = t1 - t0;
+exit:
toku_free(curr_sb.uncompressed_ptr);
return r;
}
-static int
-check_and_copy_compressed_sub_block_worker(struct rbuf curr_rbuf, struct sub_block curr_sb, FTNODE node, int child)
-{
+static int check_and_copy_compressed_sub_block_worker(struct rbuf curr_rbuf,
+ struct sub_block curr_sb,
+ FTNODE node,
+ int child) {
int r = 0;
r = read_compressed_sub_block(&curr_rbuf, &curr_sb);
if (r != 0) {
@@ -1419,7 +1533,8 @@ check_and_copy_compressed_sub_block_worker(struct rbuf curr_rbuf, struct sub_blo
bp_sb->compressed_size = curr_sb.compressed_size;
bp_sb->uncompressed_size = curr_sb.uncompressed_size;
bp_sb->compressed_ptr = toku_xmalloc(bp_sb->compressed_size);
- memcpy(bp_sb->compressed_ptr, curr_sb.compressed_ptr, bp_sb->compressed_size);
+ memcpy(
+ bp_sb->compressed_ptr, curr_sb.compressed_ptr, bp_sb->compressed_size);
exit:
return r;
}
@@ -1430,35 +1545,50 @@ static FTNODE alloc_ftnode_for_deserialize(uint32_t fullhash, BLOCKNUM blocknum)
node->fullhash = fullhash;
node->blocknum = blocknum;
node->dirty = 0;
- node->logical_rows_delta = 0;
- node->bp = nullptr;
node->oldest_referenced_xid_known = TXNID_NONE;
+ node->bp = nullptr;
+ node->ct_pair = nullptr;
return node;
}
-static int
-deserialize_ftnode_header_from_rbuf_if_small_enough (FTNODE *ftnode,
- FTNODE_DISK_DATA* ndd,
- BLOCKNUM blocknum,
- uint32_t fullhash,
- ftnode_fetch_extra *bfe,
- struct rbuf *rb,
- int fd)
+static int deserialize_ftnode_header_from_rbuf_if_small_enough(
+ FTNODE *ftnode,
+ FTNODE_DISK_DATA *ndd,
+ BLOCKNUM blocknum,
+ uint32_t fullhash,
+ ftnode_fetch_extra *bfe,
+ struct rbuf *rb,
+ int fd)
// If we have enough information in the rbuf to construct a header, then do so.
// Also fetch in the basement node if needed.
-// Return 0 if it worked. If something goes wrong (including that we are looking at some old data format that doesn't have partitions) then return nonzero.
+// Return 0 if it worked. If something goes wrong (including that we are
+// looking at some old data format that doesn't have partitions) then return
+// nonzero.
{
int r = 0;
tokutime_t t0, t1;
tokutime_t decompress_time = 0;
tokutime_t deserialize_time = 0;
+ // we must get the name from bfe and not through
+ // toku_ftnode_get_cachefile_fname_in_env as the node is not set up yet
+ const char* fname = toku_cachefile_fname_in_env(bfe->ft->cf);
t0 = toku_time_now();
FTNODE node = alloc_ftnode_for_deserialize(fullhash, blocknum);
if (rb->size < 24) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_header_from_rbuf_if_small_enough - "
+ "file[%s], blocknum[%ld], rb->size[%u] < 24\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ rb->size);
+ dump_bad_block(rb->buf, rb->size);
// TODO: What error do we return here?
// Does it even matter?
r = toku_db_badformat();
@@ -1467,14 +1597,45 @@ deserialize_ftnode_header_from_rbuf_if_small_enough (FTNODE *ftnode,
const void *magic;
rbuf_literal_bytes(rb, &magic, 8);
- if (memcmp(magic, "tokuleaf", 8)!=0 &&
- memcmp(magic, "tokunode", 8)!=0) {
+ if (memcmp(magic, "tokuleaf", 8) != 0 &&
+ memcmp(magic, "tokunode", 8) != 0) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_header_from_rbuf_if_small_enough - "
+ "file[%s], blocknum[%ld], unrecognized magic number "
+ "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ static_cast(magic)[0],
+ static_cast(magic)[1],
+ static_cast(magic)[2],
+ static_cast(magic)[3],
+ static_cast(magic)[4],
+ static_cast(magic)[5],
+ static_cast(magic)[6],
+ static_cast(magic)[7]);
+ dump_bad_block(rb->buf, rb->size);
r = toku_db_badformat();
goto cleanup;
}
node->layout_version_read_from_disk = rbuf_int(rb);
- if (node->layout_version_read_from_disk < FT_FIRST_LAYOUT_VERSION_WITH_BASEMENT_NODES) {
+ if (node->layout_version_read_from_disk <
+ FT_FIRST_LAYOUT_VERSION_WITH_BASEMENT_NODES) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_header_from_rbuf_if_small_enough - "
+ "file[%s], blocknum[%ld], node->layout_version_read_from_disk[%d] "
+ "< FT_FIRST_LAYOUT_VERSION_WITH_BASEMENT_NODES[%d]\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ node->layout_version_read_from_disk,
+ FT_FIRST_LAYOUT_VERSION_WITH_BASEMENT_NODES);
+ dump_bad_block(rb->buf, rb->size);
// This code path doesn't have to worry about upgrade.
r = toku_db_badformat();
goto cleanup;
@@ -1496,10 +1657,24 @@ deserialize_ftnode_header_from_rbuf_if_small_enough (FTNODE *ftnode,
// is too big, we may have a problem, so check that we won't overflow
// while reading the partition locations.
unsigned int nhsize;
- nhsize = serialize_node_header_size(node); // we can do this because n_children is filled in.
+ // we can do this because n_children is filled in.
+ nhsize = serialize_node_header_size(node);
unsigned int needed_size;
- needed_size = nhsize + 12; // we need 12 more so that we can read the compressed block size information that follows for the nodeinfo.
+ // we need 12 more so that we can read the compressed block size information
+ // that follows for the nodeinfo.
+ needed_size = nhsize + 12;
if (needed_size > rb->size) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_header_from_rbuf_if_small_enough - "
+ "file[%s], blocknum[%ld], needed_size[%d] > rb->size[%d]\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ needed_size,
+ rb->size);
+ dump_bad_block(rb->buf, rb->size);
r = toku_db_badformat();
goto cleanup;
}
@@ -1517,6 +1692,16 @@ deserialize_ftnode_header_from_rbuf_if_small_enough (FTNODE *ftnode,
uint32_t stored_checksum;
stored_checksum = rbuf_int(rb);
if (stored_checksum != checksum) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_header_from_rbuf_if_small_enough - "
+ "file[%s], blocknum[%ld], stored_checksum[%d] != checksum[%d]\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ stored_checksum,
+ checksum);
dump_bad_block(rb->buf, rb->size);
r = TOKUDB_BAD_CHECKSUM;
goto cleanup;
@@ -1525,9 +1710,23 @@ deserialize_ftnode_header_from_rbuf_if_small_enough (FTNODE *ftnode,
// Now we want to read the pivot information.
struct sub_block sb_node_info;
sub_block_init(&sb_node_info);
- sb_node_info.compressed_size = rbuf_int(rb); // we'll be able to read these because we checked the size earlier.
+ // we'll be able to read these because we checked the size earlier.
+ sb_node_info.compressed_size = rbuf_int(rb);
sb_node_info.uncompressed_size = rbuf_int(rb);
- if (rb->size-rb->ndone < sb_node_info.compressed_size + 8) {
+ if (rb->size - rb->ndone < sb_node_info.compressed_size + 8) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_header_from_rbuf_if_small_enough - "
+ "file[%s], blocknum[%ld], rb->size[%d] - rb->ndone[%d] < "
+ "sb_node_info.compressed_size[%d] + 8\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ rb->size,
+ rb->ndone,
+ sb_node_info.compressed_size);
+ dump_bad_block(rb->buf, rb->size);
r = toku_db_badformat();
goto cleanup;
}
@@ -1539,8 +1738,20 @@ deserialize_ftnode_header_from_rbuf_if_small_enough (FTNODE *ftnode,
sb_node_info.xsum = rbuf_int(rb);
// let's check the checksum
uint32_t actual_xsum;
- actual_xsum = toku_x1764_memory((char *)sb_node_info.compressed_ptr-8, 8+sb_node_info.compressed_size);
+ actual_xsum = toku_x1764_memory((char *)sb_node_info.compressed_ptr - 8,
+ 8 + sb_node_info.compressed_size);
if (sb_node_info.xsum != actual_xsum) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_header_from_rbuf_if_small_enough - "
+ "file[%s], blocknum[%ld], sb_node_info.xsum[%d] != actual_xsum[%d]\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ sb_node_info.xsum,
+ actual_xsum);
+ dump_bad_block(rb->buf, rb->size);
r = TOKUDB_BAD_CHECKSUM;
goto cleanup;
}
@@ -1550,18 +1761,30 @@ deserialize_ftnode_header_from_rbuf_if_small_enough (FTNODE *ftnode,
toku::scoped_malloc sb_node_info_buf(sb_node_info.uncompressed_size);
sb_node_info.uncompressed_ptr = sb_node_info_buf.get();
tokutime_t decompress_t0 = toku_time_now();
- toku_decompress(
- (Bytef *) sb_node_info.uncompressed_ptr,
- sb_node_info.uncompressed_size,
- (Bytef *) sb_node_info.compressed_ptr,
- sb_node_info.compressed_size
- );
+ toku_decompress((Bytef *)sb_node_info.uncompressed_ptr,
+ sb_node_info.uncompressed_size,
+ (Bytef *)sb_node_info.compressed_ptr,
+ sb_node_info.compressed_size);
tokutime_t decompress_t1 = toku_time_now();
decompress_time = decompress_t1 - decompress_t0;
// at this point sb->uncompressed_ptr stores the serialized node info.
r = deserialize_ftnode_info(&sb_node_info, node);
if (r != 0) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_header_from_rbuf_if_small_enough - "
+ "file[%s], blocknum[%ld], deserialize_ftnode_info failed with "
+ "%d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ r);
+ dump_bad_block(
+ static_cast(sb_node_info.uncompressed_ptr),
+ sb_node_info.uncompressed_size);
+ dump_bad_block(rb->buf, rb->size);
goto cleanup;
}
}
@@ -1586,6 +1809,17 @@ deserialize_ftnode_header_from_rbuf_if_small_enough (FTNODE *ftnode,
PAIR_ATTR attr;
r = toku_ftnode_pf_callback(node, *ndd, bfe, fd, &attr);
if (r != 0) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_header_from_rbuf_if_small_enough - "
+ "file[%s], blocknum[%ld], toku_ftnode_pf_callback failed with "
+ "%d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ r);
+ dump_bad_block(rb->buf, rb->size);
goto cleanup;
}
}
@@ -1622,12 +1856,10 @@ cleanup:
// that did not generate MSN's for messages. These new MSN's are
// generated from the root downwards, counting backwards from MIN_MSN
// and persisted in the ft header.
-static int
-deserialize_and_upgrade_internal_node(FTNODE node,
- struct rbuf *rb,
- ftnode_fetch_extra *bfe,
- STAT64INFO info)
-{
+static int deserialize_and_upgrade_internal_node(FTNODE node,
+ struct rbuf *rb,
+ ftnode_fetch_extra *bfe,
+ STAT64INFO info) {
int version = node->layout_version_read_from_disk;
if (version == FT_LAST_LAYOUT_VERSION_WITH_FINGERPRINT) {
@@ -1892,25 +2124,25 @@ deserialize_and_upgrade_leaf_node(FTNODE node,
return r;
}
-static int
-read_and_decompress_block_from_fd_into_rbuf(int fd, BLOCKNUM blocknum,
- DISKOFF offset, DISKOFF size,
- FT ft,
- struct rbuf *rb,
- /* out */ int *layout_version_p);
+static int read_and_decompress_block_from_fd_into_rbuf(
+ int fd,
+ BLOCKNUM blocknum,
+ DISKOFF offset,
+ DISKOFF size,
+ FT ft,
+ struct rbuf *rb,
+ /* out */ int *layout_version_p);
// This function upgrades a version 14 or 13 ftnode to the current
// version. NOTE: This code assumes the first field of the rbuf has
// already been read from the buffer (namely the layout_version of the
// ftnode.)
-static int
-deserialize_and_upgrade_ftnode(FTNODE node,
- FTNODE_DISK_DATA* ndd,
- BLOCKNUM blocknum,
- ftnode_fetch_extra *bfe,
- STAT64INFO info,
- int fd)
-{
+static int deserialize_and_upgrade_ftnode(FTNODE node,
+ FTNODE_DISK_DATA *ndd,
+ BLOCKNUM blocknum,
+ ftnode_fetch_extra *bfe,
+ STAT64INFO info,
+ int fd) {
int r = 0;
int version;
@@ -1929,6 +2161,16 @@ deserialize_and_upgrade_ftnode(FTNODE node,
&rb,
&version);
if (r != 0) {
+ const char* fname = toku_cachefile_fname_in_env(bfe->ft->cf);
+ fprintf(stderr,
+ "%s:%d:deserialize_and_upgrade_ftnode - "
+ "file[%s], blocknum[%ld], "
+ "read_and_decompress_block_from_fd_into_rbuf failed with %d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ r);
goto exit;
}
@@ -1944,6 +2186,21 @@ deserialize_and_upgrade_ftnode(FTNODE node,
// Copy over old version info.
node->layout_version_read_from_disk = rbuf_int(&rb); // 2. layout version
version = node->layout_version_read_from_disk;
+ if (version > FT_LAYOUT_VERSION_14) {
+ const char* fname = toku_cachefile_fname_in_env(bfe->ft->cf);
+ fprintf(stderr,
+ "%s:%d:deserialize_and_upgrade_ftnode - "
+ "file[%s], blocknum[%ld], version[%d] > "
+ "FT_LAYOUT_VERSION_14[%d]\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ version,
+ FT_LAYOUT_VERSION_14);
+ dump_bad_block(rb.buf, rb.size);
+ goto exit;
+ }
assert(version <= FT_LAYOUT_VERSION_14);
// Upgrade the current version number to the current version.
node->layout_version = FT_LAYOUT_VERSION;
@@ -1991,25 +2248,23 @@ exit:
return r;
}
-static int
-deserialize_ftnode_from_rbuf(
- FTNODE *ftnode,
- FTNODE_DISK_DATA* ndd,
- BLOCKNUM blocknum,
- uint32_t fullhash,
- ftnode_fetch_extra *bfe,
- STAT64INFO info,
- struct rbuf *rb,
- int fd
- )
-// Effect: deserializes a ftnode that is in rb (with pointer of rb just past the magic) into a FTNODE.
-{
+// Effect: deserializes a ftnode that is in rb (with pointer of rb just past the
+// magic) into a FTNODE.
+static int deserialize_ftnode_from_rbuf(FTNODE *ftnode,
+ FTNODE_DISK_DATA *ndd,
+ BLOCKNUM blocknum,
+ uint32_t fullhash,
+ ftnode_fetch_extra *bfe,
+ STAT64INFO info,
+ struct rbuf *rb,
+ int fd) {
int r = 0;
struct sub_block sb_node_info;
tokutime_t t0, t1;
tokutime_t decompress_time = 0;
tokutime_t deserialize_time = 0;
+ const char* fname = toku_cachefile_fname_in_env(bfe->ft->cf);
t0 = toku_time_now();
@@ -2019,8 +2274,26 @@ deserialize_ftnode_from_rbuf(
// first thing we do is read the header information
const void *magic;
rbuf_literal_bytes(rb, &magic, 8);
- if (memcmp(magic, "tokuleaf", 8)!=0 &&
- memcmp(magic, "tokunode", 8)!=0) {
+ if (memcmp(magic, "tokuleaf", 8) != 0 &&
+ memcmp(magic, "tokunode", 8) != 0) {
+ fprintf(stderr,
+ "%s:%d:deserialize_ftnode_from_rbuf - "
+ "file[%s], blocknum[%ld], unrecognized magic number "
+ "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ static_cast(magic)[0],
+ static_cast(magic)[1],
+ static_cast(magic)[2],
+ static_cast(magic)[3],
+ static_cast(magic)[4],
+ static_cast(magic)[5],
+ static_cast(magic)[6],
+ static_cast(magic)[7]);
+ dump_bad_block(rb->buf, rb->size);
+
r = toku_db_badformat();
goto cleanup;
}
@@ -2034,6 +2307,16 @@ deserialize_ftnode_from_rbuf(
// Perform the upgrade.
r = deserialize_and_upgrade_ftnode(node, ndd, blocknum, bfe, info, fd);
if (r != 0) {
+ fprintf(stderr,
+ "%s:%d:deserialize_ftnode_from_rbuf - "
+ "file[%s], blocknum[%ld], deserialize_and_upgrade_ftnode "
+ "failed with %d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ r);
+ dump_bad_block(rb->buf, rb->size);
goto cleanup;
}
@@ -2069,6 +2352,16 @@ deserialize_ftnode_from_rbuf(
uint32_t stored_checksum;
stored_checksum = rbuf_int(rb);
if (stored_checksum != checksum) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_from_rbuf - "
+ "file[%s], blocknum[%ld], stored_checksum[%d] != checksum[%d]\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ stored_checksum,
+ checksum);
dump_bad_block(rb->buf, rb->size);
invariant(stored_checksum == checksum);
}
@@ -2080,34 +2373,61 @@ deserialize_ftnode_from_rbuf(
r = read_and_decompress_sub_block(rb, &sb_node_info);
tokutime_t sb_decompress_t1 = toku_time_now();
decompress_time += sb_decompress_t1 - sb_decompress_t0;
- }
- if (r != 0) {
- goto cleanup;
+ if (r != 0) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_from_rbuf - "
+ "file[%s], blocknum[%ld], read_and_decompress_sub_block failed "
+ "with %d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ r);
+ dump_bad_block(
+ static_cast(sb_node_info.uncompressed_ptr),
+ sb_node_info.uncompressed_size);
+ dump_bad_block(rb->buf, rb->size);
+ goto cleanup;
+ }
}
// at this point, sb->uncompressed_ptr stores the serialized node info
r = deserialize_ftnode_info(&sb_node_info, node);
if (r != 0) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_from_rbuf - "
+ "file[%s], blocknum[%ld], deserialize_ftnode_info failed with "
+ "%d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ r);
+ dump_bad_block(rb->buf, rb->size);
goto cleanup;
}
toku_free(sb_node_info.uncompressed_ptr);
- // now that the node info has been deserialized, we can proceed to deserialize
- // the individual sub blocks
+ // now that the node info has been deserialized, we can proceed to
+ // deserialize the individual sub blocks
// setup the memory of the partitions
- // for partitions being decompressed, create either message buffer or basement node
+ // for partitions being decompressed, create either message buffer or
+ // basement node
// for partitions staying compressed, create sub_block
setup_ftnode_partitions(node, bfe, true);
- // This loop is parallelizeable, since we don't have a dependency on the work done so far.
+ // This loop is parallelizeable, since we don't have a dependency on the
+ // work done so far.
for (int i = 0; i < node->n_children; i++) {
- uint32_t curr_offset = BP_START(*ndd,i);
- uint32_t curr_size = BP_SIZE(*ndd,i);
- // the compressed, serialized partitions start at where rb is currently pointing,
- // which would be rb->buf + rb->ndone
+ uint32_t curr_offset = BP_START(*ndd, i);
+ uint32_t curr_size = BP_SIZE(*ndd, i);
+ // the compressed, serialized partitions start at where rb is currently
+ // pointing, which would be rb->buf + rb->ndone
// we need to intialize curr_rbuf to point to this place
- struct rbuf curr_rbuf = {.buf = NULL, .size = 0, .ndone = 0};
+ struct rbuf curr_rbuf = {.buf = nullptr, .size = 0, .ndone = 0};
rbuf_init(&curr_rbuf, rb->buf + curr_offset, curr_size);
//
@@ -2120,26 +2440,45 @@ deserialize_ftnode_from_rbuf(
// of the compressed partitions (also possibly none or possibly all)
// The partitions that we want to decompress and make available
// to the node, we do, the rest we simply copy in compressed
- // form into the node, and set the state of the partition to PT_COMPRESSED
+ // form into the node, and set the state of the partition to
+ // PT_COMPRESSED
//
struct sub_block curr_sb;
sub_block_init(&curr_sb);
- // curr_rbuf is passed by value to decompress_and_deserialize_worker, so there's no ugly race condition.
+ // curr_rbuf is passed by value to decompress_and_deserialize_worker,
+ // so there's no ugly race condition.
// This would be more obvious if curr_rbuf were an array.
// deserialize_ftnode_info figures out what the state
// should be and sets up the memory so that we are ready to use it
- switch (BP_STATE(node,i)) {
- case PT_AVAIL: {
+ switch (BP_STATE(node, i)) {
+ case PT_AVAIL: {
// case where we read and decompress the partition
tokutime_t partition_decompress_time;
- r = decompress_and_deserialize_worker(curr_rbuf, curr_sb, node, i,
- bfe->ft->cmp, &partition_decompress_time);
+ r = decompress_and_deserialize_worker(
+ curr_rbuf,
+ curr_sb,
+ node,
+ i,
+ bfe->ft->cmp,
+ &partition_decompress_time);
decompress_time += partition_decompress_time;
if (r != 0) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_from_rbuf - "
+ "file[%s], blocknum[%ld], childnum[%d], "
+ "decompress_and_deserialize_worker failed with %d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ i,
+ r);
+ dump_bad_block(rb->buf, rb->size);
goto cleanup;
}
break;
@@ -2148,6 +2487,19 @@ deserialize_ftnode_from_rbuf(
// case where we leave the partition in the compressed state
r = check_and_copy_compressed_sub_block_worker(curr_rbuf, curr_sb, node, i);
if (r != 0) {
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_from_rbuf - "
+ "file[%s], blocknum[%ld], childnum[%d], "
+ "check_and_copy_compressed_sub_block_worker failed with "
+ "%d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ i,
+ r);
+ dump_bad_block(rb->buf, rb->size);
goto cleanup;
}
break;
@@ -2259,8 +2611,10 @@ toku_deserialize_bp_from_disk(FTNODE node, FTNODE_DISK_DATA ndd, int childnum, i
}
// Take a ftnode partition that is in the compressed state, and make it avail
-int
-toku_deserialize_bp_from_compressed(FTNODE node, int childnum, ftnode_fetch_extra *bfe) {
+int toku_deserialize_bp_from_compressed(FTNODE node,
+ int childnum,
+ ftnode_fetch_extra *bfe) {
+
int r = 0;
assert(BP_STATE(node, childnum) == PT_COMPRESSED);
SUB_BLOCK curr_sb = BSB(node, childnum);
@@ -2275,16 +2629,30 @@ toku_deserialize_bp_from_compressed(FTNODE node, int childnum, ftnode_fetch_extr
// decompress the sub_block
tokutime_t t0 = toku_time_now();
- toku_decompress(
- (Bytef *) curr_sb->uncompressed_ptr,
- curr_sb->uncompressed_size,
- (Bytef *) curr_sb->compressed_ptr,
- curr_sb->compressed_size
- );
+ toku_decompress((Bytef *)curr_sb->uncompressed_ptr,
+ curr_sb->uncompressed_size,
+ (Bytef *)curr_sb->compressed_ptr,
+ curr_sb->compressed_size);
tokutime_t t1 = toku_time_now();
r = deserialize_ftnode_partition(curr_sb, node, childnum, bfe->ft->cmp);
+ if (r != 0) {
+ const char* fname = toku_cachefile_fname_in_env(bfe->ft->cf);
+ fprintf(stderr,
+ "%s:%d:toku_deserialize_bp_from_compressed - "
+ "file[%s], blocknum[%ld], "
+ "deserialize_ftnode_partition failed with %d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ node->blocknum.b,
+ r);
+ dump_bad_block(static_cast(curr_sb->compressed_ptr),
+ curr_sb->compressed_size);
+ dump_bad_block(static_cast(curr_sb->uncompressed_ptr),
+ curr_sb->uncompressed_size);
+ }
tokutime_t t2 = toku_time_now();
@@ -2299,26 +2667,36 @@ toku_deserialize_bp_from_compressed(FTNODE node, int childnum, ftnode_fetch_extr
return r;
}
-static int
-deserialize_ftnode_from_fd(int fd,
- BLOCKNUM blocknum,
- uint32_t fullhash,
- FTNODE *ftnode,
- FTNODE_DISK_DATA *ndd,
- ftnode_fetch_extra *bfe,
- STAT64INFO info)
-{
+static int deserialize_ftnode_from_fd(int fd,
+ BLOCKNUM blocknum,
+ uint32_t fullhash,
+ FTNODE *ftnode,
+ FTNODE_DISK_DATA *ndd,
+ ftnode_fetch_extra *bfe,
+ STAT64INFO info) {
struct rbuf rb = RBUF_INITIALIZER;
tokutime_t t0 = toku_time_now();
- read_block_from_fd_into_rbuf(fd, blocknum, bfe->ft, &rb);
+ read_block_from_fd_into_rbuf(fd, blocknum, bfe->ft, &rb);
tokutime_t t1 = toku_time_now();
// Decompress and deserialize the ftnode. Time statistics
// are taken inside this function.
- int r = deserialize_ftnode_from_rbuf(ftnode, ndd, blocknum, fullhash, bfe, info, &rb, fd);
+ int r = deserialize_ftnode_from_rbuf(
+ ftnode, ndd, blocknum, fullhash, bfe, info, &rb, fd);
if (r != 0) {
- dump_bad_block(rb.buf,rb.size);
+ const char* fname = toku_cachefile_fname_in_env(bfe->ft->cf);
+ fprintf(
+ stderr,
+ "%s:%d:deserialize_ftnode_from_fd - "
+ "file[%s], blocknum[%ld], deserialize_ftnode_from_rbuf failed with "
+ "%d\n",
+ __FILE__,
+ __LINE__,
+ fname ? fname : "unknown",
+ blocknum.b,
+ r);
+ dump_bad_block(rb.buf, rb.size);
}
bfe->bytes_read = rb.size;
@@ -2327,32 +2705,33 @@ deserialize_ftnode_from_fd(int fd,
return r;
}
-// Read ftnode from file into struct. Perform version upgrade if necessary.
-int
-toku_deserialize_ftnode_from (int fd,
- BLOCKNUM blocknum,
- uint32_t fullhash,
- FTNODE *ftnode,
- FTNODE_DISK_DATA* ndd,
- ftnode_fetch_extra *bfe
- )
// Effect: Read a node in. If possible, read just the header.
-{
+// Perform version upgrade if necessary.
+int toku_deserialize_ftnode_from(int fd,
+ BLOCKNUM blocknum,
+ uint32_t fullhash,
+ FTNODE *ftnode,
+ FTNODE_DISK_DATA *ndd,
+ ftnode_fetch_extra *bfe) {
int r = 0;
struct rbuf rb = RBUF_INITIALIZER;
- // each function below takes the appropriate io/decompression/deserialize statistics
+ // each function below takes the appropriate io/decompression/deserialize
+ // statistics
if (!bfe->read_all_partitions) {
- read_ftnode_header_from_fd_into_rbuf_if_small_enough(fd, blocknum, bfe->ft, &rb, bfe);
- r = deserialize_ftnode_header_from_rbuf_if_small_enough(ftnode, ndd, blocknum, fullhash, bfe, &rb, fd);
+ read_ftnode_header_from_fd_into_rbuf_if_small_enough(
+ fd, blocknum, bfe->ft, &rb, bfe);
+ r = deserialize_ftnode_header_from_rbuf_if_small_enough(
+ ftnode, ndd, blocknum, fullhash, bfe, &rb, fd);
} else {
// force us to do it the old way
r = -1;
}
if (r != 0) {
// Something went wrong, go back to doing it the old way.
- r = deserialize_ftnode_from_fd(fd, blocknum, fullhash, ftnode, ndd, bfe, NULL);
+ r = deserialize_ftnode_from_fd(
+ fd, blocknum, fullhash, ftnode, ndd, bfe, nullptr);
}
toku_free(rb.buf);
@@ -2722,12 +3101,14 @@ static int decompress_from_raw_block_into_rbuf_versioned(uint32_t version, uint8
return r;
}
-static int
-read_and_decompress_block_from_fd_into_rbuf(int fd, BLOCKNUM blocknum,
- DISKOFF offset, DISKOFF size,
- FT ft,
- struct rbuf *rb,
- /* out */ int *layout_version_p) {
+static int read_and_decompress_block_from_fd_into_rbuf(
+ int fd,
+ BLOCKNUM blocknum,
+ DISKOFF offset,
+ DISKOFF size,
+ FT ft,
+ struct rbuf *rb,
+ /* out */ int *layout_version_p) {
int r = 0;
if (0) printf("Deserializing Block %" PRId64 "\n", blocknum.b);
diff --git a/storage/tokudb/PerconaFT/ft/serialize/ft_node-serialize.h b/storage/tokudb/PerconaFT/ft/serialize/ft_node-serialize.h
index 3ad616053e9..678139655f0 100644
--- a/storage/tokudb/PerconaFT/ft/serialize/ft_node-serialize.h
+++ b/storage/tokudb/PerconaFT/ft/serialize/ft_node-serialize.h
@@ -46,21 +46,51 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
#include "ft/serialize/block_table.h"
unsigned int toku_serialize_ftnode_size(FTNODE node);
-int toku_serialize_ftnode_to_memory(FTNODE node, FTNODE_DISK_DATA *ndd,
- unsigned int basementnodesize,
- enum toku_compression_method compression_method,
- bool do_rebalancing, bool in_parallel,
- size_t *n_bytes_to_write, size_t *n_uncompressed_bytes,
- char **bytes_to_write);
-int toku_serialize_ftnode_to(int fd, BLOCKNUM, FTNODE node, FTNODE_DISK_DATA *ndd, bool do_rebalancing, FT ft, bool for_checkpoint);
-int toku_serialize_rollback_log_to(int fd, ROLLBACK_LOG_NODE log, SERIALIZED_ROLLBACK_LOG_NODE serialized_log, bool is_serialized,
- FT ft, bool for_checkpoint);
-void toku_serialize_rollback_log_to_memory_uncompressed(ROLLBACK_LOG_NODE log, SERIALIZED_ROLLBACK_LOG_NODE serialized);
+int toku_serialize_ftnode_to_memory(
+ FTNODE node,
+ FTNODE_DISK_DATA *ndd,
+ unsigned int basementnodesize,
+ enum toku_compression_method compression_method,
+ bool do_rebalancing,
+ bool in_parallel,
+ size_t *n_bytes_to_write,
+ size_t *n_uncompressed_bytes,
+ char **bytes_to_write);
+int toku_serialize_ftnode_to(int fd,
+ BLOCKNUM,
+ FTNODE node,
+ FTNODE_DISK_DATA *ndd,
+ bool do_rebalancing,
+ FT ft,
+ bool for_checkpoint);
+int toku_serialize_rollback_log_to(int fd,
+ ROLLBACK_LOG_NODE log,
+ SERIALIZED_ROLLBACK_LOG_NODE serialized_log,
+ bool is_serialized,
+ FT ft,
+ bool for_checkpoint);
+void toku_serialize_rollback_log_to_memory_uncompressed(
+ ROLLBACK_LOG_NODE log,
+ SERIALIZED_ROLLBACK_LOG_NODE serialized);
-int toku_deserialize_rollback_log_from(int fd, BLOCKNUM blocknum, ROLLBACK_LOG_NODE *logp, FT ft);
-int toku_deserialize_bp_from_disk(FTNODE node, FTNODE_DISK_DATA ndd, int childnum, int fd, ftnode_fetch_extra *bfe);
-int toku_deserialize_bp_from_compressed(FTNODE node, int childnum, ftnode_fetch_extra *bfe);
-int toku_deserialize_ftnode_from(int fd, BLOCKNUM off, uint32_t fullhash, FTNODE *node, FTNODE_DISK_DATA *ndd, ftnode_fetch_extra *bfe);
+int toku_deserialize_rollback_log_from(int fd,
+ BLOCKNUM blocknum,
+ ROLLBACK_LOG_NODE *logp,
+ FT ft);
+int toku_deserialize_bp_from_disk(FTNODE node,
+ FTNODE_DISK_DATA ndd,
+ int childnum,
+ int fd,
+ ftnode_fetch_extra *bfe);
+int toku_deserialize_bp_from_compressed(FTNODE node,
+ int childnum,
+ ftnode_fetch_extra *bfe);
+int toku_deserialize_ftnode_from(int fd,
+ BLOCKNUM off,
+ uint32_t fullhash,
+ FTNODE *node,
+ FTNODE_DISK_DATA *ndd,
+ ftnode_fetch_extra *bfe);
void toku_serialize_set_parallel(bool);
@@ -73,9 +103,14 @@ int decompress_from_raw_block_into_rbuf(uint8_t *raw_block, size_t raw_block_siz
// used by verify
int deserialize_ft_versioned(int fd, struct rbuf *rb, FT *ft, uint32_t version);
-void read_block_from_fd_into_rbuf(int fd, BLOCKNUM blocknum, FT ft, struct rbuf *rb);
+void read_block_from_fd_into_rbuf(int fd,
+ BLOCKNUM blocknum,
+ FT ft,
+ struct rbuf *rb);
int read_compressed_sub_block(struct rbuf *rb, struct sub_block *sb);
-int verify_ftnode_sub_block(struct sub_block *sb);
+int verify_ftnode_sub_block(struct sub_block *sb,
+ const char *fname,
+ BLOCKNUM blocknum);
void just_decompress_sub_block(struct sub_block *sb);
// used by ft-node-deserialize.cc
diff --git a/storage/tokudb/PerconaFT/ft/txn/roll.cc b/storage/tokudb/PerconaFT/ft/txn/roll.cc
index 4f374d62173..97afd2f5bdb 100644
--- a/storage/tokudb/PerconaFT/ft/txn/roll.cc
+++ b/storage/tokudb/PerconaFT/ft/txn/roll.cc
@@ -203,7 +203,7 @@ int toku_rollback_frename(BYTESTRING old_iname,
}
if (toku_stat(new_iname_full.get(), &stat) == -1) {
- if (ENOENT == errno)
+ if (ENOENT == errno || ENAMETOOLONG == errno)
new_exist = false;
else
return 1;
diff --git a/storage/tokudb/PerconaFT/ft/txn/txn.cc b/storage/tokudb/PerconaFT/ft/txn/txn.cc
index dd03073a3ec..a3ce6beb7b0 100644
--- a/storage/tokudb/PerconaFT/ft/txn/txn.cc
+++ b/storage/tokudb/PerconaFT/ft/txn/txn.cc
@@ -269,6 +269,7 @@ static txn_child_manager tcm;
.state = TOKUTXN_LIVE,
.num_pin = 0,
.client_id = 0,
+ .client_extra = nullptr,
.start_time = time(NULL),
};
@@ -705,12 +706,14 @@ bool toku_txn_has_spilled_rollback(TOKUTXN txn) {
return txn_has_spilled_rollback_logs(txn);
}
-uint64_t toku_txn_get_client_id(TOKUTXN txn) {
- return txn->client_id;
+void toku_txn_get_client_id(TOKUTXN txn, uint64_t *client_id, void **client_extra) {
+ if (client_id) *client_id = txn->client_id;
+ if (client_extra) *client_extra = txn->client_extra;
}
-void toku_txn_set_client_id(TOKUTXN txn, uint64_t client_id) {
+void toku_txn_set_client_id(TOKUTXN txn, uint64_t client_id, void *client_extra) {
txn->client_id = client_id;
+ txn->client_extra = client_extra;
}
time_t toku_txn_get_start_time(struct tokutxn *txn) {
diff --git a/storage/tokudb/PerconaFT/ft/txn/txn.h b/storage/tokudb/PerconaFT/ft/txn/txn.h
index 51a46022150..34a76aa9cad 100644
--- a/storage/tokudb/PerconaFT/ft/txn/txn.h
+++ b/storage/tokudb/PerconaFT/ft/txn/txn.h
@@ -193,6 +193,7 @@ struct tokutxn {
uint32_t num_pin; // number of threads (all hot indexes) that want this
// txn to not transition to commit or abort
uint64_t client_id;
+ void *client_extra;
time_t start_time;
};
typedef struct tokutxn *TOKUTXN;
@@ -293,8 +294,8 @@ void toku_txn_unpin_live_txn(struct tokutxn *txn);
bool toku_txn_has_spilled_rollback(struct tokutxn *txn);
-uint64_t toku_txn_get_client_id(struct tokutxn *txn);
-void toku_txn_set_client_id(struct tokutxn *txn, uint64_t client_id);
+void toku_txn_get_client_id(struct tokutxn *txn, uint64_t *client_id, void **client_extra);
+void toku_txn_set_client_id(struct tokutxn *txn, uint64_t client_id, void *client_extra);
time_t toku_txn_get_start_time(struct tokutxn *txn);
diff --git a/storage/tokudb/PerconaFT/locktree/lock_request.cc b/storage/tokudb/PerconaFT/locktree/lock_request.cc
index 22b6da9afc4..10fd2e7a208 100644
--- a/storage/tokudb/PerconaFT/locktree/lock_request.cc
+++ b/storage/tokudb/PerconaFT/locktree/lock_request.cc
@@ -65,6 +65,7 @@ void lock_request::create(void) {
toku_cond_init(&m_wait_cond, nullptr);
m_start_test_callback = nullptr;
+ m_start_before_pending_test_callback = nullptr;
m_retry_test_callback = nullptr;
}
@@ -79,7 +80,7 @@ void lock_request::destroy(void) {
}
// set the lock request parameters. this API allows a lock request to be reused.
-void lock_request::set(locktree *lt, TXNID txnid, const DBT *left_key, const DBT *right_key, lock_request::type lock_type, bool big_txn) {
+void lock_request::set(locktree *lt, TXNID txnid, const DBT *left_key, const DBT *right_key, lock_request::type lock_type, bool big_txn, void *extra) {
invariant(m_state != state::PENDING);
m_lt = lt;
m_txnid = txnid;
@@ -91,6 +92,7 @@ void lock_request::set(locktree *lt, TXNID txnid, const DBT *left_key, const DBT
m_state = state::INITIALIZED;
m_info = lt ? lt->get_lock_request_info() : nullptr;
m_big_txn = big_txn;
+ m_extra = extra;
}
// get rid of any stored left and right key copies and
@@ -173,6 +175,8 @@ int lock_request::start(void) {
m_state = state::PENDING;
m_start_time = toku_current_time_microsec() / 1000;
m_conflicting_txnid = conflicts.get(0);
+ if (m_start_before_pending_test_callback)
+ m_start_before_pending_test_callback();
toku_mutex_lock(&m_info->mutex);
insert_into_lock_requests();
if (deadlock_exists(conflicts)) {
@@ -180,7 +184,8 @@ int lock_request::start(void) {
r = DB_LOCK_DEADLOCK;
}
toku_mutex_unlock(&m_info->mutex);
- if (m_start_test_callback) m_start_test_callback(); // test callback
+ if (m_start_test_callback)
+ m_start_test_callback(); // test callback
}
if (r != DB_LOCK_NOTGRANTED) {
@@ -203,7 +208,18 @@ int lock_request::wait(uint64_t wait_time_ms, uint64_t killed_time_ms, int (*kil
toku_mutex_lock(&m_info->mutex);
+ // check again, this time locking out other retry calls
+ if (m_state == state::PENDING) {
+ retry();
+ }
+
while (m_state == state::PENDING) {
+ // check if this thread is killed
+ if (killed_callback && killed_callback()) {
+ remove_from_lock_requests();
+ complete(DB_LOCK_NOTGRANTED);
+ continue;
+ }
// compute next wait time
uint64_t t_wait;
@@ -221,13 +237,13 @@ int lock_request::wait(uint64_t wait_time_ms, uint64_t killed_time_ms, int (*kil
invariant(r == 0 || r == ETIMEDOUT);
t_now = toku_current_time_microsec();
- if (m_state == state::PENDING && (t_now >= t_end || (killed_callback && killed_callback()))) {
+ if (m_state == state::PENDING && (t_now >= t_end)) {
m_info->counters.timeout_count += 1;
-
+
// if we're still pending and we timed out, then remove our
// request from the set of lock requests and fail.
remove_from_lock_requests();
-
+
// complete sets m_state to COMPLETE, breaking us out of the loop
complete(DB_LOCK_NOTGRANTED);
}
@@ -274,13 +290,17 @@ TXNID lock_request::get_conflicting_txnid(void) const {
}
int lock_request::retry(void) {
- int r;
-
invariant(m_state == state::PENDING);
+ int r;
+ txnid_set conflicts;
+ conflicts.create();
+
if (m_type == type::WRITE) {
- r = m_lt->acquire_write_lock(m_txnid, m_left_key, m_right_key, nullptr, m_big_txn);
+ r = m_lt->acquire_write_lock(
+ m_txnid, m_left_key, m_right_key, &conflicts, m_big_txn);
} else {
- r = m_lt->acquire_read_lock(m_txnid, m_left_key, m_right_key, nullptr, m_big_txn);
+ r = m_lt->acquire_read_lock(
+ m_txnid, m_left_key, m_right_key, &conflicts, m_big_txn);
}
// if the acquisition succeeded then remove ourselves from the
@@ -288,44 +308,63 @@ int lock_request::retry(void) {
if (r == 0) {
remove_from_lock_requests();
complete(r);
- if (m_retry_test_callback) m_retry_test_callback(); // test callback
+ if (m_retry_test_callback)
+ m_retry_test_callback(); // test callback
toku_cond_broadcast(&m_wait_cond);
+ } else {
+ m_conflicting_txnid = conflicts.get(0);
}
+ conflicts.destroy();
return r;
}
-void lock_request::retry_all_lock_requests(locktree *lt) {
+void lock_request::retry_all_lock_requests(
+ locktree *lt,
+ void (*after_retry_all_test_callback)(void)) {
lt_lock_request_info *info = lt->get_lock_request_info();
- // if a thread reads this bit to be true, then it should go ahead and
- // take the locktree mutex and retry lock requests. we use this bit
- // to prevent every single thread from waiting on the locktree mutex
- // in order to retry requests, especially when no requests actually exist.
- //
- // it is important to note that this bit only provides an optimization.
- // it is not problematic for it to be true when it should be false,
- // but it can be problematic for it to be false when it should be true.
- // therefore, the lock request code must ensures that when lock requests
- // are added to this locktree, the bit is set.
- // see lock_request::insert_into_lock_requests()
- if (!info->should_retry_lock_requests) {
+ // if there are no pending lock requests than there is nothing to do
+ // the unlocked data race on pending_is_empty is OK since lock requests
+ // are retried after added to the pending set.
+ if (info->pending_is_empty)
return;
+
+ // get my retry generation (post increment of retry_want)
+ unsigned long long my_retry_want = (info->retry_want += 1);
+
+ toku_mutex_lock(&info->retry_mutex);
+
+ // here is the group retry algorithm.
+ // get the latest retry_want count and use it as the generation number of
+ // this retry operation. if this retry generation is > the last retry
+ // generation, then do the lock retries. otherwise, no lock retries
+ // are needed.
+ if ((my_retry_want - 1) == info->retry_done) {
+ for (;;) {
+ if (!info->running_retry) {
+ info->running_retry = true;
+ info->retry_done = info->retry_want;
+ toku_mutex_unlock(&info->retry_mutex);
+ retry_all_lock_requests_info(info);
+ if (after_retry_all_test_callback)
+ after_retry_all_test_callback();
+ toku_mutex_lock(&info->retry_mutex);
+ info->running_retry = false;
+ toku_cond_broadcast(&info->retry_cv);
+ break;
+ } else {
+ toku_cond_wait(&info->retry_cv, &info->retry_mutex);
+ }
+ }
}
+ toku_mutex_unlock(&info->retry_mutex);
+}
+void lock_request::retry_all_lock_requests_info(lt_lock_request_info *info) {
toku_mutex_lock(&info->mutex);
-
- // let other threads know that they need not retry lock requests at this time.
- //
- // the motivation here is that if a bunch of threads have already released
- // their locks in the rangetree, then its probably okay for only one thread
- // to iterate over the list of requests and retry them. otherwise, at high
- // thread counts and a large number of pending lock requests, you could
- // end up wasting a lot of cycles.
- info->should_retry_lock_requests = false;
-
- size_t i = 0;
- while (i < info->pending_lock_requests.size()) {
+ // retry all of the pending lock requests.
+ for (size_t i = 0; i < info->pending_lock_requests.size();) {
lock_request *request;
int r = info->pending_lock_requests.fetch(i, &request);
invariant_zero(r);
@@ -346,6 +385,30 @@ void lock_request::retry_all_lock_requests(locktree *lt) {
toku_mutex_unlock(&info->mutex);
}
+void *lock_request::get_extra(void) const {
+ return m_extra;
+}
+
+void lock_request::kill_waiter(void) {
+ remove_from_lock_requests();
+ complete(DB_LOCK_NOTGRANTED);
+ toku_cond_broadcast(&m_wait_cond);
+}
+
+void lock_request::kill_waiter(locktree *lt, void *extra) {
+ lt_lock_request_info *info = lt->get_lock_request_info();
+ toku_mutex_lock(&info->mutex);
+ for (size_t i = 0; i < info->pending_lock_requests.size(); i++) {
+ lock_request *request;
+ int r = info->pending_lock_requests.fetch(i, &request);
+ if (r == 0 && request->get_extra() == extra) {
+ request->kill_waiter();
+ break;
+ }
+ }
+ toku_mutex_unlock(&info->mutex);
+}
+
// find another lock request by txnid. must hold the mutex.
lock_request *lock_request::find_lock_request(const TXNID &txnid) {
lock_request *request;
@@ -360,27 +423,30 @@ lock_request *lock_request::find_lock_request(const TXNID &txnid) {
void lock_request::insert_into_lock_requests(void) {
uint32_t idx;
lock_request *request;
- int r = m_info->pending_lock_requests.find_zero(m_txnid, &request, &idx);
+ int r = m_info->pending_lock_requests.find_zero(
+ m_txnid, &request, &idx);
invariant(r == DB_NOTFOUND);
r = m_info->pending_lock_requests.insert_at(this, idx);
invariant_zero(r);
-
- // ensure that this bit is true, now that at least one lock request is in the set
- m_info->should_retry_lock_requests = true;
+ m_info->pending_is_empty = false;
}
// remove this lock request from the locktree's set. must hold the mutex.
void lock_request::remove_from_lock_requests(void) {
uint32_t idx;
lock_request *request;
- int r = m_info->pending_lock_requests.find_zero(m_txnid, &request, &idx);
+ int r = m_info->pending_lock_requests.find_zero(
+ m_txnid, &request, &idx);
invariant_zero(r);
invariant(request == this);
r = m_info->pending_lock_requests.delete_at(idx);
invariant_zero(r);
+ if (m_info->pending_lock_requests.size() == 0)
+ m_info->pending_is_empty = true;
}
-int lock_request::find_by_txnid(lock_request * const &request, const TXNID &txnid) {
+int lock_request::find_by_txnid(lock_request *const &request,
+ const TXNID &txnid) {
TXNID request_txnid = request->m_txnid;
if (request_txnid < txnid) {
return -1;
@@ -395,6 +461,10 @@ void lock_request::set_start_test_callback(void (*f)(void)) {
m_start_test_callback = f;
}
+void lock_request::set_start_before_pending_test_callback(void (*f)(void)) {
+ m_start_before_pending_test_callback = f;
+}
+
void lock_request::set_retry_test_callback(void (*f)(void)) {
m_retry_test_callback = f;
}
diff --git a/storage/tokudb/PerconaFT/locktree/lock_request.h b/storage/tokudb/PerconaFT/locktree/lock_request.h
index 48d1279cde2..a8d8cb7785b 100644
--- a/storage/tokudb/PerconaFT/locktree/lock_request.h
+++ b/storage/tokudb/PerconaFT/locktree/lock_request.h
@@ -78,7 +78,7 @@ public:
// effect: Resets the lock request parameters, allowing it to be reused.
// requires: Lock request was already created at some point
- void set(locktree *lt, TXNID txnid, const DBT *left_key, const DBT *right_key, type lock_type, bool big_txn);
+ void set(locktree *lt, TXNID txnid, const DBT *left_key, const DBT *right_key, type lock_type, bool big_txn, void *extra = nullptr);
// effect: Tries to acquire a lock described by this lock request.
// returns: The return code of locktree::acquire_[write,read]_lock()
@@ -107,14 +107,24 @@ public:
TXNID get_conflicting_txnid(void) const;
// effect: Retries all of the lock requests for the given locktree.
- // Any lock requests successfully restarted is completed and woken up.
+ // Any lock requests successfully restarted is completed and woken
+ // up.
// The rest remain pending.
- static void retry_all_lock_requests(locktree *lt);
+ static void retry_all_lock_requests(
+ locktree *lt,
+ void (*after_retry_test_callback)(void) = nullptr);
+ static void retry_all_lock_requests_info(lt_lock_request_info *info);
void set_start_test_callback(void (*f)(void));
+ void set_start_before_pending_test_callback(void (*f)(void));
void set_retry_test_callback(void (*f)(void));
-private:
+ void *get_extra(void) const;
+
+ void kill_waiter(void);
+ static void kill_waiter(locktree *lt, void *extra);
+
+ private:
enum state {
UNINITIALIZED,
INITIALIZED,
@@ -152,6 +162,8 @@ private:
// locktree that this lock request is for.
struct lt_lock_request_info *m_info;
+ void *m_extra;
+
// effect: tries again to acquire the lock described by this lock request
// returns: 0 if retrying the request succeeded and is now complete
int retry(void);
@@ -184,9 +196,10 @@ private:
void copy_keys(void);
- static int find_by_txnid(lock_request * const &request, const TXNID &txnid);
+ static int find_by_txnid(lock_request *const &request, const TXNID &txnid);
void (*m_start_test_callback)(void);
+ void (*m_start_before_pending_test_callback)(void);
void (*m_retry_test_callback)(void);
friend class lock_request_unit_test;
diff --git a/storage/tokudb/PerconaFT/locktree/locktree.cc b/storage/tokudb/PerconaFT/locktree/locktree.cc
index d3596d47eeb..2fbf078bdd6 100644
--- a/storage/tokudb/PerconaFT/locktree/locktree.cc
+++ b/storage/tokudb/PerconaFT/locktree/locktree.cc
@@ -80,21 +80,24 @@ void locktree::create(locktree_manager *mgr, DICTIONARY_ID dict_id, const compar
m_sto_end_early_count = 0;
m_sto_end_early_time = 0;
- m_lock_request_info.pending_lock_requests.create();
- ZERO_STRUCT(m_lock_request_info.mutex);
- toku_mutex_init(&m_lock_request_info.mutex, nullptr);
- m_lock_request_info.should_retry_lock_requests = false;
- ZERO_STRUCT(m_lock_request_info.counters);
+ m_lock_request_info.init();
+}
- // Threads read the should retry bit without a lock
- // for performance. It's ok to read the wrong value.
- // - If you think you should but you shouldn't, you waste a little time.
- // - If you think you shouldn't but you should, then some other thread
- // will come around to do the work of retrying requests instead of you.
- TOKU_VALGRIND_HG_DISABLE_CHECKING(
- &m_lock_request_info.should_retry_lock_requests,
- sizeof(m_lock_request_info.should_retry_lock_requests));
- TOKU_DRD_IGNORE_VAR(m_lock_request_info.should_retry_lock_requests);
+void lt_lock_request_info::init(void) {
+ pending_lock_requests.create();
+ pending_is_empty = true;
+ ZERO_STRUCT(mutex);
+ toku_mutex_init(&mutex, nullptr);
+ retry_want = retry_done = 0;
+ ZERO_STRUCT(counters);
+ ZERO_STRUCT(retry_mutex);
+ toku_mutex_init(&retry_mutex, nullptr);
+ toku_cond_init(&retry_cv, nullptr);
+ running_retry = false;
+
+ TOKU_VALGRIND_HG_DISABLE_CHECKING(&pending_is_empty,
+ sizeof(pending_is_empty));
+ TOKU_DRD_IGNORE_VAR(pending_is_empty);
}
void locktree::destroy(void) {
@@ -104,11 +107,18 @@ void locktree::destroy(void) {
m_rangetree->destroy();
toku_free(m_rangetree);
m_sto_buffer.destroy();
- m_lock_request_info.pending_lock_requests.destroy();
+ m_lock_request_info.destroy();
+}
+
+void lt_lock_request_info::destroy(void) {
+ pending_lock_requests.destroy();
+ toku_mutex_destroy(&mutex);
+ toku_mutex_destroy(&retry_mutex);
+ toku_cond_destroy(&retry_cv);
}
void locktree::add_reference(void) {
- (void) toku_sync_add_and_fetch(&m_reference_count, 1);
+ (void)toku_sync_add_and_fetch(&m_reference_count, 1);
}
uint32_t locktree::release_reference(void) {
diff --git a/storage/tokudb/PerconaFT/locktree/locktree.h b/storage/tokudb/PerconaFT/locktree/locktree.h
index 710f9e7db06..1ba7a51b124 100644
--- a/storage/tokudb/PerconaFT/locktree/locktree.h
+++ b/storage/tokudb/PerconaFT/locktree/locktree.h
@@ -38,12 +38,14 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
#pragma once
-#include
-#include
-#include
+#include
+
+#include
+#include
+#include
-#include // just for DICTIONARY_ID..
#include
+#include // just for DICTIONARY_ID..
#include
@@ -80,20 +82,33 @@ namespace toku {
// Lock request state for some locktree
struct lt_lock_request_info {
omt pending_lock_requests;
+ std::atomic_bool pending_is_empty;
toku_mutex_t mutex;
bool should_retry_lock_requests;
lt_counters counters;
+ std::atomic_ullong retry_want;
+ unsigned long long retry_done;
+ toku_mutex_t retry_mutex;
+ toku_cond_t retry_cv;
+ bool running_retry;
+
+ void init(void);
+ void destroy(void);
};
- // The locktree manager manages a set of locktrees, one for each open dictionary.
- // Locktrees are retrieved from the manager. When they are no longer needed, they
- // are be released by the user.
+ // The locktree manager manages a set of locktrees, one for each open
+ // dictionary. Locktrees are retrieved from the manager. When they are no
+ // longer needed, they are be released by the user.
class locktree_manager {
- public:
+ public:
// param: create_cb, called just after a locktree is first created.
// destroy_cb, called just before a locktree is destroyed.
- // escalate_cb, called after a locktree is escalated (with extra param)
- void create(lt_create_cb create_cb, lt_destroy_cb destroy_cb, lt_escalate_cb escalate_cb, void *extra);
+ // escalate_cb, called after a locktree is escalated (with extra
+ // param)
+ void create(lt_create_cb create_cb,
+ lt_destroy_cb destroy_cb,
+ lt_escalate_cb escalate_cb,
+ void *extra);
void destroy(void);
@@ -159,6 +174,8 @@ namespace toku {
// Add time t to the escalator's wait time statistics
void add_escalator_wait_time(uint64_t t);
+ void kill_waiter(void *extra);
+
private:
static const uint64_t DEFAULT_MAX_LOCK_MEMORY = 64L * 1024 * 1024;
diff --git a/storage/tokudb/PerconaFT/locktree/manager.cc b/storage/tokudb/PerconaFT/locktree/manager.cc
index 4708cdf4a5a..91ff7c5a007 100644
--- a/storage/tokudb/PerconaFT/locktree/manager.cc
+++ b/storage/tokudb/PerconaFT/locktree/manager.cc
@@ -483,4 +483,17 @@ void locktree_manager::get_status(LTM_STATUS statp) {
*statp = ltm_status;
}
+void locktree_manager::kill_waiter(void *extra) {
+ mutex_lock();
+ int r = 0;
+ size_t num_locktrees = m_locktree_map.size();
+ for (size_t i = 0; i < num_locktrees; i++) {
+ locktree *lt;
+ r = m_locktree_map.fetch(i, <);
+ invariant_zero(r);
+ lock_request::kill_waiter(lt, extra);
+ }
+ mutex_unlock();
+}
+
} /* namespace toku */
diff --git a/storage/tokudb/PerconaFT/locktree/tests/kill_waiter.cc b/storage/tokudb/PerconaFT/locktree/tests/kill_waiter.cc
new file mode 100644
index 00000000000..8d93c0bbbab
--- /dev/null
+++ b/storage/tokudb/PerconaFT/locktree/tests/kill_waiter.cc
@@ -0,0 +1,100 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+
+// test the lock manager kill waiter function
+
+#include "locktree.h"
+#include "lock_request.h"
+#include "test.h"
+#include "locktree_unit_test.h"
+#include
+#include
+
+namespace toku {
+
+const uint64_t my_lock_wait_time = 1000 * 1000;
+const uint64_t my_killed_time = 500 * 1000;
+const int n_locks = 4;
+
+static int my_killed_callback(void) {
+ if (1) fprintf(stderr, "%s:%u %s\n", __FILE__, __LINE__, __FUNCTION__);
+ return 0;
+}
+
+static void locktree_release_lock(locktree *lt, TXNID txn_id, const DBT *left, const DBT *right) {
+ range_buffer buffer;
+ buffer.create();
+ buffer.append(left, right);
+ lt->release_locks(txn_id, &buffer);
+ buffer.destroy();
+}
+
+static void wait_lock(lock_request *lr, std::atomic_int *done) {
+ int r = lr->wait(my_lock_wait_time, my_killed_time, my_killed_callback);
+ assert(r == DB_LOCK_NOTGRANTED);
+ *done = 1;
+}
+
+static void test_kill_waiter(void) {
+ int r;
+
+ locktree_manager mgr;
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
+
+ DICTIONARY_ID dict_id = { 1 };
+ locktree *lt = mgr.get_lt(dict_id, dbt_comparator, nullptr);
+
+ const DBT *one = get_dbt(1);
+
+ lock_request locks[n_locks];
+ std::thread waiters[n_locks-1];
+ for (int i = 0; i < n_locks; i++) {
+ locks[i].create();
+ locks[i].set(lt, i+1, one, one, lock_request::type::WRITE, false, &waiters[i]);
+ }
+
+ // txn 'n_locks' grabs the lock
+ r = locks[n_locks-1].start();
+ assert_zero(r);
+
+ for (int i = 0; i < n_locks-1; i++) {
+ r = locks[i].start();
+ assert(r == DB_LOCK_NOTGRANTED);
+ }
+
+ std::atomic_int done[n_locks-1];
+ for (int i = 0; i < n_locks-1; i++) {
+ done[i] = 0;
+ waiters[i] = std::thread(wait_lock, &locks[i], &done[i]);
+ }
+
+ for (int i = 0; i < n_locks-1; i++) {
+ assert(!done[i]);
+ }
+
+ sleep(1);
+ for (int i = 0; i < n_locks-1; i++) {
+ mgr.kill_waiter(&waiters[i]);
+ while (!done[i]) sleep(1);
+ waiters[i].join();
+ for (int j = i+1; j < n_locks-1; j++)
+ assert(!done[j]);
+ }
+
+ locktree_release_lock(lt, n_locks, one, one);
+
+ for (int i = 0; i < n_locks; i++) {
+ locks[i].destroy();
+ }
+
+ mgr.release_lt(lt);
+ mgr.destroy();
+}
+
+} /* namespace toku */
+
+int main(void) {
+ toku::test_kill_waiter();
+ return 0;
+}
+
diff --git a/storage/tokudb/PerconaFT/locktree/tests/lock_request_killed.cc b/storage/tokudb/PerconaFT/locktree/tests/lock_request_killed.cc
index efd4092906b..ec464444271 100644
--- a/storage/tokudb/PerconaFT/locktree/tests/lock_request_killed.cc
+++ b/storage/tokudb/PerconaFT/locktree/tests/lock_request_killed.cc
@@ -51,8 +51,9 @@ static uint64_t t_do_kill;
static int my_killed_callback(void) {
uint64_t t_now = toku_current_time_microsec();
+ if (t_now == t_last_kill)
+ return 0;
assert(t_now >= t_last_kill);
- assert(t_now - t_last_kill >= my_killed_time * 1000 / 2); // div by 2 for valgrind which is not very accurate
t_last_kill = t_now;
killed_calls++;
if (t_now >= t_do_kill)
diff --git a/storage/tokudb/PerconaFT/locktree/tests/lock_request_not_killed.cc b/storage/tokudb/PerconaFT/locktree/tests/lock_request_not_killed.cc
index 702e2e2626c..647b4d3c418 100644
--- a/storage/tokudb/PerconaFT/locktree/tests/lock_request_not_killed.cc
+++ b/storage/tokudb/PerconaFT/locktree/tests/lock_request_not_killed.cc
@@ -52,7 +52,6 @@ static uint64_t t_last_kill;
static int my_killed_callback(void) {
uint64_t t_now = toku_current_time_microsec();
assert(t_now >= t_last_kill);
- assert(t_now - t_last_kill >= my_killed_time * 1000 / 2); // div by 2 for valgrind which is not very accurate
t_last_kill = t_now;
killed_calls++;
return 0;
diff --git a/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_release_wait.cc b/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_release_wait.cc
new file mode 100644
index 00000000000..717628f9df7
--- /dev/null
+++ b/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_release_wait.cc
@@ -0,0 +1,91 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+
+// test the race between start, release, and wait. since start does not put
+// its lock request into the pending set, the blocking txn could release its
+// lock before the first txn waits. this will block the first txn because its
+// lock request is not known when the lock is released. the bug fix is to try
+// again when lock retries are locked out.
+
+#include "lock_request.h"
+#include
+#include
+#include "locktree.h"
+#include "locktree_unit_test.h"
+#include "test.h"
+
+namespace toku {
+
+ const uint64_t my_lock_wait_time = 1000 * 1000; // ms
+ const uint64_t my_killed_time = 1 * 1000; // ms
+
+ static uint64_t t_wait;
+
+ static int my_killed_callback(void) {
+ uint64_t t_now = toku_current_time_microsec();
+ assert(t_now >= t_wait);
+ if (t_now - t_wait >= my_killed_time * 1000)
+ abort();
+ return 0;
+ }
+
+ static void locktree_release_lock(locktree *lt,
+ TXNID txn_id,
+ const DBT *left,
+ const DBT *right) {
+ range_buffer buffer;
+ buffer.create();
+ buffer.append(left, right);
+ lt->release_locks(txn_id, &buffer);
+ buffer.destroy();
+ }
+
+ static void test_start_release_wait(void) {
+ int r;
+
+ locktree_manager mgr;
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
+
+ DICTIONARY_ID dict_id = {1};
+ locktree *lt = mgr.get_lt(dict_id, dbt_comparator, nullptr);
+
+ const DBT *one = get_dbt(1);
+
+ // a locks one
+ lock_request a;
+ a.create();
+ a.set(lt, 1, one, one, lock_request::type::WRITE, false);
+ r = a.start();
+ assert(r == 0);
+
+ // b tries to lock one, fails
+ lock_request b;
+ b.create();
+ b.set(lt, 2, one, one, lock_request::type::WRITE, false);
+ r = b.start();
+ assert(r == DB_LOCK_NOTGRANTED);
+
+ // a releases its lock
+ locktree_release_lock(lt, 1, one, one);
+
+ // b waits for one, gets locks immediately
+ t_wait = toku_current_time_microsec();
+ r = b.wait(my_lock_wait_time, my_killed_time, my_killed_callback);
+ assert(r == 0);
+
+ // b releases its lock so we can exit cleanly
+ locktree_release_lock(lt, 2, one, one);
+
+ a.destroy();
+ b.destroy();
+
+ mgr.release_lt(lt);
+ mgr.destroy();
+ }
+
+} /* namespace toku */
+
+int main(void) {
+ toku::test_start_release_wait();
+ return 0;
+}
diff --git a/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_race.cc b/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_race.cc
index 3b653e9c6ef..5c28701c49e 100644
--- a/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_race.cc
+++ b/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_race.cc
@@ -34,12 +34,14 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
along with PerconaFT. If not, see .
======= */
-#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
+#ident \
+ "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
-#include
-#include "test.h"
-#include "locktree.h"
#include "lock_request.h"
+#include
+#include
+#include "locktree.h"
+#include "test.h"
// Test FT-633, the data race on the lock request between ::start and ::retry
// This test is non-deterministic. It uses sleeps at 2 critical places to
@@ -47,90 +49,65 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
namespace toku {
-struct locker_arg {
- locktree *_lt;
- TXNID _id;
- const DBT *_key;
+ static void locker_callback(void) { usleep(10000); }
- locker_arg(locktree *lt, TXNID id, const DBT *key) : _lt(lt), _id(id), _key(key) {
- }
-};
+ static void run_locker(locktree *lt, TXNID txnid, const DBT *key) {
+ int i;
+ for (i = 0; i < 1000; i++) {
+ lock_request request;
+ request.create();
-static void locker_callback(void) {
- usleep(10000);
-}
+ request.set(lt, txnid, key, key, lock_request::type::WRITE, false);
-static void run_locker(locktree *lt, TXNID txnid, const DBT *key) {
- int i;
- for (i = 0; i < 1000; i++) {
+ // set the test callbacks
+ request.set_start_test_callback(locker_callback);
+ request.set_retry_test_callback(locker_callback);
- lock_request request;
- request.create();
+ // try to acquire the lock
+ int r = request.start();
+ if (r == DB_LOCK_NOTGRANTED) {
+ // wait for the lock to be granted
+ r = request.wait(10 * 1000);
+ }
- request.set(lt, txnid, key, key, lock_request::type::WRITE, false);
+ if (r == 0) {
+ // release the lock
+ range_buffer buffer;
+ buffer.create();
+ buffer.append(key, key);
+ lt->release_locks(txnid, &buffer);
+ buffer.destroy();
- // set the test callbacks
- request.set_start_test_callback(locker_callback);
- request.set_retry_test_callback(locker_callback);
+ // retry pending lock requests
+ lock_request::retry_all_lock_requests(lt);
+ }
- // try to acquire the lock
- int r = request.start();
- if (r == DB_LOCK_NOTGRANTED) {
- // wait for the lock to be granted
- r = request.wait(10 * 1000);
+ request.destroy();
+ memset(&request, 0xab, sizeof request);
+
+ toku_pthread_yield();
+ if ((i % 10) == 0)
+ std::cerr << std::this_thread::get_id() << " " << i
+ << std::endl;
}
-
- if (r == 0) {
- // release the lock
- range_buffer buffer;
- buffer.create();
- buffer.append(key, key);
- lt->release_locks(txnid, &buffer);
- buffer.destroy();
-
- // retry pending lock requests
- lock_request::retry_all_lock_requests(lt);
- }
-
- request.destroy();
- memset(&request, 0xab, sizeof request);
-
- toku_pthread_yield();
- if ((i % 10) == 0)
- std::cout << toku_pthread_self() << " " << i << std::endl;
}
-}
-
-static void *locker(void *v_arg) {
- locker_arg *arg = static_cast(v_arg);
- run_locker(arg->_lt, arg->_id, arg->_key);
- return arg;
-}
} /* namespace toku */
int main(void) {
- int r;
-
toku::locktree lt;
- DICTIONARY_ID dict_id = { 1 };
+ DICTIONARY_ID dict_id = {1};
lt.create(nullptr, dict_id, toku::dbt_comparator);
const DBT *one = toku::get_dbt(1);
const int n_workers = 2;
- toku_pthread_t ids[n_workers];
+ std::thread worker[n_workers];
for (int i = 0; i < n_workers; i++) {
- toku::locker_arg *arg = new toku::locker_arg(<, i, one);
- r = toku_pthread_create(&ids[i], nullptr, toku::locker, arg);
- assert_zero(r);
+ worker[i] = std::thread(toku::run_locker, <, i, one);
}
for (int i = 0; i < n_workers; i++) {
- void *ret;
- r = toku_pthread_join(ids[i], &ret);
- assert_zero(r);
- toku::locker_arg *arg = static_cast(ret);
- delete arg;
+ worker[i].join();
}
lt.release_reference();
diff --git a/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_race_3.cc b/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_race_3.cc
new file mode 100644
index 00000000000..1a05b396f10
--- /dev/null
+++ b/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_race_3.cc
@@ -0,0 +1,133 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*======
+This file is part of PerconaFT.
+
+
+Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
+
+ PerconaFT is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License, version 2,
+ as published by the Free Software Foundation.
+
+ PerconaFT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with PerconaFT. If not, see .
+
+----------------------------------------
+
+ PerconaFT is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License, version 3,
+ as published by the Free Software Foundation.
+
+ PerconaFT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with PerconaFT. If not, see .
+======= */
+
+#ident \
+ "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
+
+#include "lock_request.h"
+#include
+#include
+#include
+#include "locktree.h"
+#include "test.h"
+
+// Suppose that 3 threads are running a lock acquire, release, retry sequence.
+// There is a race in the retry algorithm with 2 threads running lock retry
+// simultaneously. The first thread to run retry sets a flag that will cause
+// the second thread to skip the lock retries. If the first thread progressed
+// past the contended lock, then the second threa will HANG until its lock timer
+// pops, even when the contended lock is no longer held.
+
+// This test exposes this problem as a test hang. The group retry algorithm
+// fixes the race in the lock request retry algorihm and this test should no
+// longer hang.
+
+namespace toku {
+
+ // use 1000 when after_retry_all is implemented, otherwise use 100000
+ static const int n_tests = 1000; // 100000;
+
+ static void after_retry_all(void) { usleep(10000); }
+
+ static void run_locker(locktree *lt,
+ TXNID txnid,
+ const DBT *key,
+ pthread_barrier_t *b) {
+ for (int i = 0; i < n_tests; i++) {
+ int r;
+ r = pthread_barrier_wait(b);
+ assert(r == 0 || r == PTHREAD_BARRIER_SERIAL_THREAD);
+
+ lock_request request;
+ request.create();
+
+ request.set(lt, txnid, key, key, lock_request::type::WRITE, false);
+
+ // try to acquire the lock
+ r = request.start();
+ if (r == DB_LOCK_NOTGRANTED) {
+ // wait for the lock to be granted
+ r = request.wait(1000 * 1000);
+ }
+
+ if (r == 0) {
+ // release the lock
+ range_buffer buffer;
+ buffer.create();
+ buffer.append(key, key);
+ lt->release_locks(txnid, &buffer);
+ buffer.destroy();
+
+ // retry pending lock requests
+ lock_request::retry_all_lock_requests(lt, after_retry_all);
+ }
+
+ request.destroy();
+ memset(&request, 0xab, sizeof request);
+
+ toku_pthread_yield();
+ if ((i % 10) == 0)
+ std::cerr << std::this_thread::get_id() << " " << i
+ << std::endl;
+ }
+ }
+
+} /* namespace toku */
+
+int main(void) {
+ toku::locktree lt;
+ DICTIONARY_ID dict_id = {1};
+ lt.create(nullptr, dict_id, toku::dbt_comparator);
+
+ const DBT *one = toku::get_dbt(1);
+
+ const int n_workers = 3;
+ std::thread worker[n_workers];
+ pthread_barrier_t b;
+ int r = pthread_barrier_init(&b, nullptr, n_workers);
+ assert(r == 0);
+ for (int i = 0; i < n_workers; i++) {
+ worker[i] = std::thread(toku::run_locker, <, i, one, &b);
+ }
+ for (int i = 0; i < n_workers; i++) {
+ worker[i].join();
+ }
+ r = pthread_barrier_destroy(&b);
+ assert(r == 0);
+ lt.release_reference();
+ lt.destroy();
+ return 0;
+}
diff --git a/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_wait_race_2.cc b/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_wait_race_2.cc
new file mode 100644
index 00000000000..4b6dadd440f
--- /dev/null
+++ b/storage/tokudb/PerconaFT/locktree/tests/lock_request_start_retry_wait_race_2.cc
@@ -0,0 +1,135 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*======
+This file is part of PerconaFT.
+
+
+Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
+
+ PerconaFT is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License, version 2,
+ as published by the Free Software Foundation.
+
+ PerconaFT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with PerconaFT. If not, see .
+
+----------------------------------------
+
+ PerconaFT is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License, version 3,
+ as published by the Free Software Foundation.
+
+ PerconaFT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with PerconaFT. If not, see .
+======= */
+
+#ident \
+ "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
+
+#include "lock_request.h"
+#include
+#include
+#include
+#include "locktree.h"
+#include "test.h"
+
+// Suppose that 2 threads are running a lock acquire, release, retry sequence.
+// There is a race between the acquire and the release with 2 threads.
+// If thread 1 acquires a lock, and thread 2 tries to acquire the same lock and
+// fails, thread 1 may release its lock and retry pending lock requests BEFORE
+// thread 2 adds itself to the pending lock requests. If this happens, then
+// thread 2 will HANG until its lock timer expires even when the lock it is
+// waiting for is FREE.
+
+// This test exposes this problem as a test hang. If the race is fixed, then
+// the test runs to completion.
+
+namespace toku {
+
+ static void start_before_pending(void) { usleep(10000); }
+
+ static void run_locker(locktree *lt,
+ TXNID txnid,
+ const DBT *key,
+ pthread_barrier_t *b) {
+ for (int i = 0; i < 100000; i++) {
+ int r;
+ r = pthread_barrier_wait(b);
+ assert(r == 0 || r == PTHREAD_BARRIER_SERIAL_THREAD);
+
+ lock_request request;
+ request.create();
+ request.set(lt, txnid, key, key, lock_request::type::WRITE, false);
+
+ // if the callback is included, then the race is easy to reproduce.
+ // Otherwise, several test runs may be required before the race
+ // happens.
+ request.set_start_before_pending_test_callback(
+ start_before_pending);
+
+ // try to acquire the lock
+ r = request.start();
+ if (r == DB_LOCK_NOTGRANTED) {
+ // wait for the lock to be granted
+ r = request.wait(1000 * 1000);
+ }
+
+ if (r == 0) {
+ // release the lock
+ range_buffer buffer;
+ buffer.create();
+ buffer.append(key, key);
+ lt->release_locks(txnid, &buffer);
+ buffer.destroy();
+
+ // retry pending lock requests
+ lock_request::retry_all_lock_requests(lt);
+ }
+
+ request.destroy();
+ memset(&request, 0xab, sizeof request);
+
+ toku_pthread_yield();
+ if ((i % 10) == 0)
+ std::cerr << std::this_thread::get_id() << " " << i
+ << std::endl;
+ }
+ }
+
+} /* namespace toku */
+
+int main(void) {
+ toku::locktree lt;
+ DICTIONARY_ID dict_id = {1};
+ lt.create(nullptr, dict_id, toku::dbt_comparator);
+
+ const DBT *one = toku::get_dbt(1);
+
+ const int n_workers = 2;
+ std::thread worker[n_workers];
+ pthread_barrier_t b;
+ int r = pthread_barrier_init(&b, nullptr, n_workers);
+ assert(r == 0);
+ for (int i = 0; i < n_workers; i++) {
+ worker[i] = std::thread(toku::run_locker, <, i, one, &b);
+ }
+ for (int i = 0; i < n_workers; i++) {
+ worker[i].join();
+ }
+ r = pthread_barrier_destroy(&b);
+ assert(r == 0);
+ lt.release_reference();
+ lt.destroy();
+ return 0;
+}
diff --git a/storage/tokudb/PerconaFT/portability/toku_debug_sync.h b/storage/tokudb/PerconaFT/portability/toku_debug_sync.h
new file mode 100644
index 00000000000..4a959cab1fe
--- /dev/null
+++ b/storage/tokudb/PerconaFT/portability/toku_debug_sync.h
@@ -0,0 +1,77 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*======
+This file is part of PerconaFT.
+
+
+Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
+
+ PerconaFT is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License, version 2,
+ as published by the Free Software Foundation.
+
+ PerconaFT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with PerconaFT. If not, see .
+
+----------------------------------------
+
+ PerconaFT is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License, version 3,
+ as published by the Free Software Foundation.
+
+ PerconaFT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with PerconaFT. If not, see .
+======= */
+
+#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
+
+#pragma once
+
+struct tokutxn;
+
+#if defined(ENABLED_DEBUG_SYNC)
+
+/*
+ the below macros are defined in my_global.h, which is included in m_string.h,
+ the same macros are defined in TokuSetupCompiler.cmake as compiler options,
+ undefine them here to avoid build errors
+*/
+#undef __STDC_FORMAT_MACROS
+#undef __STDC_LIMIT_MACROS
+
+#include "m_string.h"
+#include "debug_sync.h"
+
+void toku_txn_get_client_id(struct tokutxn *txn,
+ uint64_t *client_id,
+ void **client_extra);
+
+inline void toku_debug_sync(struct tokutxn *txn, const char *sync_point_name) {
+ uint64_t client_id;
+ void *client_extra;
+ THD *thd;
+
+ if (likely(!opt_debug_sync_timeout))
+ return;
+
+ toku_txn_get_client_id(txn, &client_id, &client_extra);
+ thd = reinterpret_cast(client_extra);
+ debug_sync(thd, sync_point_name, strlen(sync_point_name));
+}
+
+#else // defined(ENABLED_DEBUG_SYNC)
+
+inline void toku_debug_sync(struct tokutxn *, const char *) {};
+
+#endif // defined(ENABLED_DEBUG_SYNC)
diff --git a/storage/tokudb/PerconaFT/portability/toku_portability.h b/storage/tokudb/PerconaFT/portability/toku_portability.h
index f127b0fe172..28ea8014f53 100644
--- a/storage/tokudb/PerconaFT/portability/toku_portability.h
+++ b/storage/tokudb/PerconaFT/portability/toku_portability.h
@@ -121,6 +121,7 @@ typedef int64_t toku_off_t;
#include "toku_htod.h"
#include "toku_assert.h"
#include "toku_crash.h"
+#include "toku_debug_sync.h"
#define UU(x) x __attribute__((__unused__))
@@ -183,8 +184,10 @@ extern void *realloc(void*, size_t) __THROW __attribute__((__deprecat
# pragma GCC poison u_int32_t
# pragma GCC poison u_int64_t
# pragma GCC poison BOOL
+#if !defined(MYSQL_TOKUDB_ENGINE)
# pragma GCC poison FALSE
# pragma GCC poison TRUE
+#endif // MYSQL_TOKUDB_ENGINE
#endif
#pragma GCC poison __sync_fetch_and_add
#pragma GCC poison __sync_fetch_and_sub
diff --git a/storage/tokudb/PerconaFT/src/tests/test_iterate_live_transactions.cc b/storage/tokudb/PerconaFT/src/tests/test_iterate_live_transactions.cc
index c5561cdf90f..1eb04a06594 100644
--- a/storage/tokudb/PerconaFT/src/tests/test_iterate_live_transactions.cc
+++ b/storage/tokudb/PerconaFT/src/tests/test_iterate_live_transactions.cc
@@ -55,7 +55,8 @@ static int iterate_callback(DB_TXN *txn,
iterate_row_locks_callback iterate_locks,
void *locks_extra, void *extra) {
uint64_t txnid = txn->id64(txn);
- uint64_t client_id = txn->get_client_id(txn);
+ uint64_t client_id; void *client_extra;
+ txn->get_client_id(txn, &client_id, &client_extra);
iterate_extra *info = reinterpret_cast(extra);
DB *db;
DBT left_key, right_key;
@@ -93,13 +94,13 @@ int test_main(int UU(argc), char *const UU(argv[])) {
r = env->open(env, TOKU_TEST_FILENAME, env_flags, 0755); CKERR(r);
r = env->txn_begin(env, NULL, &txn1, 0); CKERR(r);
- txn1->set_client_id(txn1, 0);
+ txn1->set_client_id(txn1, 0, nullptr);
txnid1 = txn1->id64(txn1);
r = env->txn_begin(env, NULL, &txn2, 0); CKERR(r);
- txn2->set_client_id(txn2, 1);
+ txn2->set_client_id(txn2, 1, nullptr);
txnid2 = txn2->id64(txn2);
r = env->txn_begin(env, NULL, &txn3, 0); CKERR(r);
- txn3->set_client_id(txn3, 2);
+ txn3->set_client_id(txn3, 2, nullptr);
txnid3 = txn3->id64(txn3);
{
diff --git a/storage/tokudb/PerconaFT/src/tests/test_stress0.cc b/storage/tokudb/PerconaFT/src/tests/test_stress0.cc
index 88140dd1731..037ffdd312d 100644
--- a/storage/tokudb/PerconaFT/src/tests/test_stress0.cc
+++ b/storage/tokudb/PerconaFT/src/tests/test_stress0.cc
@@ -93,7 +93,8 @@ static int iterate_txns(DB_TXN *txn,
iterate_row_locks_callback iterate_locks,
void *locks_extra, void *extra) {
uint64_t txnid = txn->id64(txn);
- uint64_t client_id = txn->get_client_id(txn);
+ uint64_t client_id; void *client_extra;
+ txn->get_client_id(txn, &client_id, &client_extra);
invariant_null(extra);
invariant(txnid > 0);
invariant(client_id == 0);
diff --git a/storage/tokudb/PerconaFT/src/tests/transactional_fileops.cc b/storage/tokudb/PerconaFT/src/tests/transactional_fileops.cc
index c1e7c5b21c4..858a1d70f7f 100644
--- a/storage/tokudb/PerconaFT/src/tests/transactional_fileops.cc
+++ b/storage/tokudb/PerconaFT/src/tests/transactional_fileops.cc
@@ -87,6 +87,7 @@ setup (void) {
else error_file = stderr;
r=db_env_create(&env, 0); CKERR(r);
+ env->set_dir_per_db(env, true);
env->set_errfile(env, error_file ? error_file : stderr);
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
}
@@ -431,6 +432,14 @@ test_fileops_3(void) {
r = env->dbrename(env, txn_a, "a.db", NULL, "d.db", 0);
CKERR2(r, EEXIST);
+ // verify correct error return code when trying to
+ // rename a dictionary to a name that is beyond the limit
+ // of the operating system.
+ char longname[FILENAME_MAX+11];
+ memset(longname, 'b', FILENAME_MAX+7);
+ memcpy(longname+FILENAME_MAX+7, ".db", 4);
+ r = env->dbrename(env, txn_a, "a.db", NULL, longname, 0);
+ CKERR2(r, ENAMETOOLONG);
r=txn_a->abort(txn_a); CKERR(r);
}
diff --git a/storage/tokudb/PerconaFT/src/ydb.cc b/storage/tokudb/PerconaFT/src/ydb.cc
index 6dd8564e6a1..abf8d3dfd17 100644
--- a/storage/tokudb/PerconaFT/src/ydb.cc
+++ b/storage/tokudb/PerconaFT/src/ydb.cc
@@ -2775,6 +2775,10 @@ static void env_set_killed_callback(DB_ENV *env, uint64_t default_killed_time_ms
env->i->killed_callback = killed_callback;
}
+static void env_kill_waiter(DB_ENV *env, void *extra) {
+ env->i->ltm.kill_waiter(extra);
+}
+
static void env_do_backtrace(DB_ENV *env) {
if (env->i->errcall) {
db_env_do_backtrace_errfunc((toku_env_err_func) toku_env_err, (const void *) env);
@@ -2877,6 +2881,7 @@ toku_env_create(DB_ENV ** envp, uint32_t flags) {
USENV(set_dir_per_db);
USENV(get_dir_per_db);
USENV(get_data_dir);
+ USENV(kill_waiter);
#undef USENV
// unlocked methods
@@ -3061,28 +3066,31 @@ env_dbremove_subdb(DB_ENV * env, DB_TXN * txn, const char *fname, const char *db
// see if we can acquire a table lock for the given dname.
// requires: write lock on dname in the directory. dictionary
// open, close, and begin checkpoint cannot occur.
-// returns: true if we could open, lock, and close a dictionary
-// with the given dname, false otherwise.
-static bool
+// returns: zero if we could open, lock, and close a dictionary
+// with the given dname, errno otherwise.
+static int
can_acquire_table_lock(DB_ENV *env, DB_TXN *txn, const char *iname_in_env) {
int r;
- bool got_lock = false;
DB *db;
r = toku_db_create(&db, env, 0);
assert_zero(r);
r = toku_db_open_iname(db, txn, iname_in_env, 0, 0);
- assert_zero(r);
- r = toku_db_pre_acquire_table_lock(db, txn);
- if (r == 0) {
- got_lock = true;
- } else {
- got_lock = false;
+ if(r) {
+ if (r == ENAMETOOLONG)
+ toku_ydb_do_error(env, r, "File name too long!\n");
+ goto exit;
}
- r = toku_db_close(db);
- assert_zero(r);
-
- return got_lock;
+ r = toku_db_pre_acquire_table_lock(db, txn);
+ if (r) {
+ r = DB_LOCK_NOTGRANTED;
+ }
+exit:
+ if(db) {
+ int r2 = toku_db_close(db);
+ assert_zero(r2);
+ }
+ return r;
}
static int
@@ -3295,8 +3303,8 @@ env_dbrename(DB_ENV *env, DB_TXN *txn, const char *fname, const char *dbname, co
// otherwise, we're okay in marking this ft as remove on
// commit. no new handles can open for this dictionary
// because the txn has directory write locks on the dname
- if (txn && !can_acquire_table_lock(env, txn, new_iname.get())) {
- r = DB_LOCK_NOTGRANTED;
+ if (txn) {
+ r = can_acquire_table_lock(env, txn, new_iname.get());
}
// We don't do anything at the ft or cachetable layer for rename.
// We just update entries in the environment's directory.
diff --git a/storage/tokudb/PerconaFT/src/ydb_row_lock.cc b/storage/tokudb/PerconaFT/src/ydb_row_lock.cc
index 913e1a44faf..d612262e2ab 100644
--- a/storage/tokudb/PerconaFT/src/ydb_row_lock.cc
+++ b/storage/tokudb/PerconaFT/src/ydb_row_lock.cc
@@ -181,7 +181,16 @@ int toku_db_get_range_lock(DB *db, DB_TXN *txn, const DBT *left_key, const DBT *
request.create();
int r = toku_db_start_range_lock(db, txn, left_key, right_key, lock_type, &request);
if (r == DB_LOCK_NOTGRANTED) {
+ toku_debug_sync(db_txn_struct_i(txn)->tokutxn,
+ "toku_range_lock_before_wait");
r = toku_db_wait_range_lock(db, txn, &request);
+ if (r == DB_LOCK_NOTGRANTED)
+ toku_debug_sync(db_txn_struct_i(txn)->tokutxn,
+ "toku_range_lock_not_granted_after_wait");
+ }
+ else if (r == 0) {
+ toku_debug_sync(db_txn_struct_i(txn)->tokutxn,
+ "toku_range_lock_granted_immediately");
}
request.destroy();
@@ -191,9 +200,13 @@ int toku_db_get_range_lock(DB *db, DB_TXN *txn, const DBT *left_key, const DBT *
// Setup and start an asynchronous lock request.
int toku_db_start_range_lock(DB *db, DB_TXN *txn, const DBT *left_key, const DBT *right_key,
toku::lock_request::type lock_type, toku::lock_request *request) {
+ uint64_t client_id;
+ void *client_extra;
DB_TXN *txn_anc = txn_oldest_ancester(txn);
TXNID txn_anc_id = txn_anc->id64(txn_anc);
- request->set(db->i->lt, txn_anc_id, left_key, right_key, lock_type, toku_is_big_txn(txn_anc));
+ txn->get_client_id(txn, &client_id, &client_extra);
+ request->set(db->i->lt, txn_anc_id, left_key, right_key, lock_type,
+ toku_is_big_txn(txn_anc), client_extra);
const int r = request->start();
if (r == 0) {
@@ -241,6 +254,8 @@ int toku_db_get_point_write_lock(DB *db, DB_TXN *txn, const DBT *key) {
// acquire a point write lock on the key for a given txn.
// this does not block the calling thread.
void toku_db_grab_write_lock (DB *db, DBT *key, TOKUTXN tokutxn) {
+ uint64_t client_id;
+ void *client_extra;
DB_TXN *txn = toku_txn_get_container_db_txn(tokutxn);
DB_TXN *txn_anc = txn_oldest_ancester(txn);
TXNID txn_anc_id = txn_anc->id64(txn_anc);
@@ -248,7 +263,10 @@ void toku_db_grab_write_lock (DB *db, DBT *key, TOKUTXN tokutxn) {
// This lock request must succeed, so we do not want to wait
toku::lock_request request;
request.create();
- request.set(db->i->lt, txn_anc_id, key, key, toku::lock_request::type::WRITE, toku_is_big_txn(txn_anc));
+ txn->get_client_id(txn, &client_id, &client_extra);
+ request.set(db->i->lt, txn_anc_id, key, key,
+ toku::lock_request::type::WRITE, toku_is_big_txn(txn_anc),
+ client_extra);
int r = request.start();
invariant_zero(r);
db_txn_note_row_lock(db, txn_anc, key, key);
diff --git a/storage/tokudb/PerconaFT/src/ydb_txn.cc b/storage/tokudb/PerconaFT/src/ydb_txn.cc
index ae1f93011d1..40b479055f2 100644
--- a/storage/tokudb/PerconaFT/src/ydb_txn.cc
+++ b/storage/tokudb/PerconaFT/src/ydb_txn.cc
@@ -323,12 +323,12 @@ int locked_txn_abort(DB_TXN *txn) {
return r;
}
-static void locked_txn_set_client_id(DB_TXN *txn, uint64_t client_id) {
- toku_txn_set_client_id(db_txn_struct_i(txn)->tokutxn, client_id);
+static void locked_txn_set_client_id(DB_TXN *txn, uint64_t client_id, void *client_extra) {
+ toku_txn_set_client_id(db_txn_struct_i(txn)->tokutxn, client_id, client_extra);
}
-static uint64_t locked_txn_get_client_id(DB_TXN *txn) {
- return toku_txn_get_client_id(db_txn_struct_i(txn)->tokutxn);
+static void locked_txn_get_client_id(DB_TXN *txn, uint64_t *client_id, void **client_extra) {
+ toku_txn_get_client_id(db_txn_struct_i(txn)->tokutxn, client_id, client_extra);
}
static int toku_txn_discard(DB_TXN *txn, uint32_t flags) {
diff --git a/storage/tokudb/PerconaFT/tools/CMakeLists.txt b/storage/tokudb/PerconaFT/tools/CMakeLists.txt
index 30ca883c4ba..b64c9b9c45a 100644
--- a/storage/tokudb/PerconaFT/tools/CMakeLists.txt
+++ b/storage/tokudb/PerconaFT/tools/CMakeLists.txt
@@ -6,6 +6,14 @@ foreach(tool ${tools})
add_dependencies(${tool} install_tdb_h)
target_link_libraries(${tool} ${LIBTOKUDB}_static ft_static z lzma snappy ${LIBTOKUPORTABILITY}_static ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_SYSTEM_LIBS})
+ # detect when we are being built as a subproject
+ if (DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
+ if ((CMAKE_BUILD_TYPE MATCHES "Debug") AND
+ (CMAKE_CXX_FLAGS_DEBUG MATCHES " -DENABLED_DEBUG_SYNC"))
+ target_link_libraries(${tool} sql binlog rpl master slave)
+ endif()
+ endif ()
+
add_space_separated_property(TARGET ${tool} COMPILE_FLAGS -fvisibility=hidden)
endforeach(tool)
diff --git a/storage/tokudb/PerconaFT/tools/ftverify.cc b/storage/tokudb/PerconaFT/tools/ftverify.cc
index 2324249ba00..ee40b991ea6 100644
--- a/storage/tokudb/PerconaFT/tools/ftverify.cc
+++ b/storage/tokudb/PerconaFT/tools/ftverify.cc
@@ -325,7 +325,7 @@ check_block(BLOCKNUM blocknum, int64_t UU(blocksize), int64_t UU(address), void
}
just_decompress_sub_block(&sb);
- r = verify_ftnode_sub_block(&sb);
+ r = verify_ftnode_sub_block(&sb, nullptr, blocknum);
if (r != 0) {
printf(" Uncompressed child partition %d checksum failed.\n", i);
failure++;
diff --git a/storage/tokudb/PerconaFT/tools/tokuftdump.cc b/storage/tokudb/PerconaFT/tools/tokuftdump.cc
index f6d777b4161..2838ae5182e 100644
--- a/storage/tokudb/PerconaFT/tools/tokuftdump.cc
+++ b/storage/tokudb/PerconaFT/tools/tokuftdump.cc
@@ -158,7 +158,8 @@ static void dump_descriptor(DESCRIPTOR d) {
static void open_header(int fd, FT *header, CACHEFILE cf) {
FT ft = NULL;
int r;
- r = toku_deserialize_ft_from (fd, MAX_LSN, &ft);
+ const char *fn = toku_cachefile_fname_in_env(cf);
+ r = toku_deserialize_ft_from (fd, fn, MAX_LSN, &ft);
if (r != 0) {
fprintf(stderr, "%s: can not deserialize from %s error %d\n", arg0, fname, r);
exit(1);
diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc
index 15276f2fb85..9079d15c7fd 100644
--- a/storage/tokudb/ha_tokudb.cc
+++ b/storage/tokudb/ha_tokudb.cc
@@ -532,51 +532,6 @@ typedef struct index_read_info {
DBT* orig_key;
} *INDEX_READ_INFO;
-static int ai_poll_fun(void *extra, float progress) {
- LOADER_CONTEXT context = (LOADER_CONTEXT)extra;
- if (thd_killed(context->thd)) {
- sprintf(context->write_status_msg, "The process has been killed, aborting add index.");
- return ER_ABORTING_CONNECTION;
- }
- float percentage = progress * 100;
- sprintf(context->write_status_msg, "Adding of indexes about %.1f%% done", percentage);
- thd_proc_info(context->thd, context->write_status_msg);
-#ifdef HA_TOKUDB_HAS_THD_PROGRESS
- thd_progress_report(context->thd, (unsigned long long) percentage, 100);
-#endif
- return 0;
-}
-
-static int loader_poll_fun(void *extra, float progress) {
- LOADER_CONTEXT context = (LOADER_CONTEXT)extra;
- if (thd_killed(context->thd)) {
- sprintf(context->write_status_msg, "The process has been killed, aborting bulk load.");
- return ER_ABORTING_CONNECTION;
- }
- float percentage = progress * 100;
- sprintf(context->write_status_msg, "Loading of data about %.1f%% done", percentage);
- thd_proc_info(context->thd, context->write_status_msg);
-#ifdef HA_TOKUDB_HAS_THD_PROGRESS
- thd_progress_report(context->thd, (unsigned long long) percentage, 100);
-#endif
- return 0;
-}
-
-static void loader_ai_err_fun(DB *db, int i, int err, DBT *key, DBT *val, void *error_extra) {
- LOADER_CONTEXT context = (LOADER_CONTEXT)error_extra;
- assert_always(context->ha);
- context->ha->set_loader_error(err);
-}
-
-static void loader_dup_fun(DB *db, int i, int err, DBT *key, DBT *val, void *error_extra) {
- LOADER_CONTEXT context = (LOADER_CONTEXT)error_extra;
- assert_always(context->ha);
- context->ha->set_loader_error(err);
- if (err == DB_KEYEXIST) {
- context->ha->set_dup_value_for_pk(key);
- }
-}
-
//
// smart DBT callback function for optimize
// in optimize, we want to flatten DB by doing
@@ -3396,11 +3351,13 @@ void ha_tokudb::start_bulk_insert(ha_rows rows) {
lc.thd = thd;
lc.ha = this;
-
- error = loader->set_poll_function(loader, loader_poll_fun, &lc);
+
+ error = loader->set_poll_function(
+ loader, ha_tokudb::bulk_insert_poll, &lc);
assert_always(!error);
- error = loader->set_error_callback(loader, loader_dup_fun, &lc);
+ error = loader->set_error_callback(
+ loader, ha_tokudb::loader_dup, &lc);
assert_always(!error);
trx->stmt_progress.using_loader = true;
@@ -3413,6 +3370,47 @@ void ha_tokudb::start_bulk_insert(ha_rows rows) {
}
TOKUDB_HANDLER_DBUG_VOID_RETURN;
}
+int ha_tokudb::bulk_insert_poll(void* extra, float progress) {
+ LOADER_CONTEXT context = (LOADER_CONTEXT)extra;
+ if (thd_killed(context->thd)) {
+ sprintf(context->write_status_msg,
+ "The process has been killed, aborting bulk load.");
+ return ER_ABORTING_CONNECTION;
+ }
+ float percentage = progress * 100;
+ sprintf(context->write_status_msg,
+ "Loading of data t %s about %.1f%% done",
+ context->ha->share->full_table_name(),
+ percentage);
+ thd_proc_info(context->thd, context->write_status_msg);
+#ifdef HA_TOKUDB_HAS_THD_PROGRESS
+ thd_progress_report(context->thd, (unsigned long long)percentage, 100);
+#endif
+ return 0;
+}
+void ha_tokudb::loader_add_index_err(DB* db,
+ int i,
+ int err,
+ DBT* key,
+ DBT* val,
+ void* error_extra) {
+ LOADER_CONTEXT context = (LOADER_CONTEXT)error_extra;
+ assert_always(context->ha);
+ context->ha->set_loader_error(err);
+}
+void ha_tokudb::loader_dup(DB* db,
+ int i,
+ int err,
+ DBT* key,
+ DBT* val,
+ void* error_extra) {
+ LOADER_CONTEXT context = (LOADER_CONTEXT)error_extra;
+ assert_always(context->ha);
+ context->ha->set_loader_error(err);
+ if (err == DB_KEYEXIST) {
+ context->ha->set_dup_value_for_pk(key);
+ }
+}
//
// Method that is called at the end of many calls to insert rows
@@ -8179,12 +8177,14 @@ int ha_tokudb::tokudb_add_index(
goto cleanup;
}
- error = indexer->set_poll_function(indexer, ai_poll_fun, &lc);
+ error = indexer->set_poll_function(
+ indexer, ha_tokudb::tokudb_add_index_poll, &lc);
if (error) {
goto cleanup;
}
- error = indexer->set_error_callback(indexer, loader_ai_err_fun, &lc);
+ error = indexer->set_error_callback(
+ indexer, ha_tokudb::loader_add_index_err, &lc);
if (error) {
goto cleanup;
}
@@ -8239,12 +8239,14 @@ int ha_tokudb::tokudb_add_index(
goto cleanup;
}
- error = loader->set_poll_function(loader, loader_poll_fun, &lc);
+ error =
+ loader->set_poll_function(loader, ha_tokudb::bulk_insert_poll, &lc);
if (error) {
goto cleanup;
}
- error = loader->set_error_callback(loader, loader_ai_err_fun, &lc);
+ error = loader->set_error_callback(
+ loader, ha_tokudb::loader_add_index_err, &lc);
if (error) {
goto cleanup;
}
@@ -8451,6 +8453,24 @@ cleanup:
thd_proc_info(thd, orig_proc_info);
TOKUDB_HANDLER_DBUG_RETURN(error ? error : loader_error);
}
+int ha_tokudb::tokudb_add_index_poll(void* extra, float progress) {
+ LOADER_CONTEXT context = (LOADER_CONTEXT)extra;
+ if (thd_killed(context->thd)) {
+ sprintf(context->write_status_msg,
+ "The process has been killed, aborting add index.");
+ return ER_ABORTING_CONNECTION;
+ }
+ float percentage = progress * 100;
+ sprintf(context->write_status_msg,
+ "Adding of indexes to %s about %.1f%% done",
+ context->ha->share->full_table_name(),
+ percentage);
+ thd_proc_info(context->thd, context->write_status_msg);
+#ifdef HA_TOKUDB_HAS_THD_PROGRESS
+ thd_progress_report(context->thd, (unsigned long long)percentage, 100);
+#endif
+ return 0;
+}
//
// Internal function called by ha_tokudb::add_index and ha_tokudb::alter_table_phase2
diff --git a/storage/tokudb/ha_tokudb.h b/storage/tokudb/ha_tokudb.h
index a25e322568d..f90f4130b37 100644
--- a/storage/tokudb/ha_tokudb.h
+++ b/storage/tokudb/ha_tokudb.h
@@ -799,6 +799,19 @@ public:
#else
void start_bulk_insert(ha_rows rows);
#endif
+ static int bulk_insert_poll(void* extra, float progress);
+ static void loader_add_index_err(DB* db,
+ int i,
+ int err,
+ DBT* key,
+ DBT* val,
+ void* error_extra);
+ static void loader_dup(DB* db,
+ int i,
+ int err,
+ DBT* key,
+ DBT* val,
+ void* error_extra);
int end_bulk_insert();
int end_bulk_insert(bool abort);
@@ -938,17 +951,23 @@ public:
#endif
private:
- int tokudb_add_index(
- TABLE *table_arg,
- KEY *key_info,
- uint num_of_keys,
- DB_TXN* txn,
- bool* inc_num_DBs,
- bool* modified_DB
- );
- void restore_add_index(TABLE* table_arg, uint num_of_keys, bool incremented_numDBs, bool modified_DBs);
- int drop_indexes(TABLE *table_arg, uint *key_num, uint num_of_keys, KEY *key_info, DB_TXN* txn);
- void restore_drop_indexes(TABLE *table_arg, uint *key_num, uint num_of_keys);
+ int tokudb_add_index(TABLE* table_arg,
+ KEY* key_info,
+ uint num_of_keys,
+ DB_TXN* txn,
+ bool* inc_num_DBs,
+ bool* modified_DB);
+ static int tokudb_add_index_poll(void *extra, float progress);
+ void restore_add_index(TABLE* table_arg,
+ uint num_of_keys,
+ bool incremented_numDBs,
+ bool modified_DBs);
+ int drop_indexes(TABLE* table_arg,
+ uint* key_num,
+ uint num_of_keys,
+ KEY* key_info,
+ DB_TXN* txn);
+ void restore_drop_indexes(TABLE* table_arg, uint* key_num, uint num_of_keys);
public:
// delete all rows from the table
diff --git a/storage/tokudb/hatoku_hton.cc b/storage/tokudb/hatoku_hton.cc
index 5e49e8d95d0..2ae9cdc071b 100644
--- a/storage/tokudb/hatoku_hton.cc
+++ b/storage/tokudb/hatoku_hton.cc
@@ -67,6 +67,7 @@ static bool tokudb_show_status(
static void tokudb_handle_fatal_signal(handlerton* hton, THD* thd, int sig);
#endif
static int tokudb_close_connection(handlerton* hton, THD* thd);
+static void tokudb_kill_connection(handlerton *hton, THD *thd);
static int tokudb_commit(handlerton* hton, THD* thd, bool all);
static int tokudb_rollback(handlerton* hton, THD* thd, bool all);
#if TOKU_INCLUDE_XA
@@ -343,6 +344,7 @@ static int tokudb_init_func(void *p) {
tokudb_hton->create = tokudb_create_handler;
tokudb_hton->close_connection = tokudb_close_connection;
+ tokudb_hton->kill_connection = tokudb_kill_connection;
tokudb_hton->savepoint_offset = sizeof(SP_INFO_T);
tokudb_hton->savepoint_set = tokudb_savepoint;
@@ -766,6 +768,12 @@ static int tokudb_close_connection(handlerton* hton, THD* thd) {
return error;
}
+void tokudb_kill_connection(handlerton *hton, THD *thd) {
+ TOKUDB_DBUG_ENTER("");
+ db_env->kill_waiter(db_env, thd);
+ DBUG_VOID_RETURN;
+}
+
bool tokudb_flush_logs(handlerton * hton) {
TOKUDB_DBUG_ENTER("");
int error;
diff --git a/storage/tokudb/mysql-test/tokudb/r/kill_query_blocked_in_lt.result b/storage/tokudb/mysql-test/tokudb/r/kill_query_blocked_in_lt.result
new file mode 100644
index 00000000000..27423a840e8
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/kill_query_blocked_in_lt.result
@@ -0,0 +1,26 @@
+### connection default
+CREATE TABLE t (a INT PRIMARY KEY, b INT) ENGINE=TokuDB;
+INSERT INTO t (a, b) VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5),
+(6, 6), (7, 7), (8, 8), (9, 9), (10, 10),
+(11, 11), (12, 12), (13, 13), (14, 14), (15, 15),
+(16, 16), (17, 17), (18, 18), (19, 19), (20, 20);
+### connection con1
+SET DEBUG_SYNC= 'toku_range_lock_granted_immediately SIGNAL lock_granted WAIT_FOR lock_granted_continue';
+UPDATE t SET b=1 WHERE a BETWEEN 5 AND 10;
+### connection default
+SET DEBUG_SYNC= 'now WAIT_FOR lock_granted';
+### connection con2
+SET DEBUG_SYNC= 'toku_range_lock_before_wait SIGNAL lock_not_granted WAIT_FOR lock_not_granted_continue';
+SET DEBUG_SYNC= 'toku_range_lock_not_granted_after_wait SIGNAL lock_not_granted_after_wait';
+UPDATE t SET b=1 WHERE a BETWEEN 5 AND 10;
+### connection default
+SET DEBUG_SYNC= 'now SIGNAL lock_not_granted_continue WAIT_FOR lock_not_granted';
+KILL QUERY con2_id
+SET DEBUG_SYNC= 'now SIGNAL lock_granted_continue WAIT_FOR lock_not_granted_after_wait';
+### connection con1
+### reap
+### connection con2
+### reap
+ERROR 70100: Query execution was interrupted
+### connection default
+DROP TABLE t;
diff --git a/storage/tokudb/mysql-test/tokudb/r/locks-select-update-3.result b/storage/tokudb/mysql-test/tokudb/r/locks-select-update-3.result
index 8b31bf5a280..3f05f65661c 100644
--- a/storage/tokudb/mysql-test/tokudb/r/locks-select-update-3.result
+++ b/storage/tokudb/mysql-test/tokudb/r/locks-select-update-3.result
@@ -1,6 +1,4 @@
-SET DEFAULT_STORAGE_ENGINE='tokudb';
-drop table if exists t;
-create table t (a int primary key, b int);
+create table t (a int primary key, b int) engine=tokudb;
insert into t values (1,0);
set session transaction isolation level read committed;
begin;
@@ -8,6 +6,7 @@ select * from t where a=1 for update;
a b
1 0
update t set b=b+1 where a=1;
+set session tokudb_lock_timeout=60000;
set session transaction isolation level read committed;
begin;
select * from t where a=1 for update;
diff --git a/storage/tokudb/mysql-test/tokudb/t/kill_query_blocked_in_lt.test b/storage/tokudb/mysql-test/tokudb/t/kill_query_blocked_in_lt.test
new file mode 100644
index 00000000000..7a79f73c89b
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/kill_query_blocked_in_lt.test
@@ -0,0 +1,56 @@
+--source include/have_tokudb.inc
+--source include/have_debug_sync.inc
+
+--echo ### connection default
+
+CREATE TABLE t (a INT PRIMARY KEY, b INT) ENGINE=TokuDB;
+
+INSERT INTO t (a, b) VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5),
+ (6, 6), (7, 7), (8, 8), (9, 9), (10, 10),
+ (11, 11), (12, 12), (13, 13), (14, 14), (15, 15),
+ (16, 16), (17, 17), (18, 18), (19, 19), (20, 20);
+
+--connect(con1, localhost, root)
+--connect(con2, localhost, root)
+
+--connection con1
+--echo ### connection con1
+SET DEBUG_SYNC= 'toku_range_lock_granted_immediately SIGNAL lock_granted WAIT_FOR lock_granted_continue';
+--send UPDATE t SET b=1 WHERE a BETWEEN 5 AND 10
+
+--connection default
+--echo ### connection default
+SET DEBUG_SYNC= 'now WAIT_FOR lock_granted';
+
+--connection con2
+--echo ### connection con2
+--let $con2_id= `SELECT CONNECTION_ID()`
+SET DEBUG_SYNC= 'toku_range_lock_before_wait SIGNAL lock_not_granted WAIT_FOR lock_not_granted_continue';
+SET DEBUG_SYNC= 'toku_range_lock_not_granted_after_wait SIGNAL lock_not_granted_after_wait';
+--send UPDATE t SET b=1 WHERE a BETWEEN 5 AND 10
+
+--connection default
+--echo ### connection default
+SET DEBUG_SYNC= 'now SIGNAL lock_not_granted_continue WAIT_FOR lock_not_granted';
+
+--disable_query_log
+--eval KILL QUERY $con2_id
+--enable_query_log
+--echo KILL QUERY con2_id
+SET DEBUG_SYNC= 'now SIGNAL lock_granted_continue WAIT_FOR lock_not_granted_after_wait';
+
+--connection con1
+--echo ### connection con1
+--echo ### reap
+--reap
+
+--connection con2
+--echo ### connection con2
+--echo ### reap
+--error ER_QUERY_INTERRUPTED
+--reap
+
+--connection default
+--echo ### connection default
+
+DROP TABLE t;
diff --git a/storage/tokudb/mysql-test/tokudb/t/locks-select-update-3.test b/storage/tokudb/mysql-test/tokudb/t/locks-select-update-3.test
index a563f061add..fcd89d5783f 100644
--- a/storage/tokudb/mysql-test/tokudb/t/locks-select-update-3.test
+++ b/storage/tokudb/mysql-test/tokudb/t/locks-select-update-3.test
@@ -1,12 +1,8 @@
source include/have_tokudb.inc;
+source include/count_sessions.inc;
# test that select for update is executed with serializable isolation
-SET DEFAULT_STORAGE_ENGINE='tokudb';
-
---disable_warnings
-drop table if exists t;
---enable_warnings
-create table t (a int primary key, b int);
+create table t (a int primary key, b int) engine=tokudb;
insert into t values (1,0);
set session transaction isolation level read committed;
begin;
@@ -15,6 +11,7 @@ select * from t where a=1 for update;
# t2 update
update t set b=b+1 where a=1;
connect(conn1,localhost,root);
+set session tokudb_lock_timeout=60000;
set session transaction isolation level read committed;
begin;
# t2 select for update, should hang until t1 commits
@@ -33,3 +30,4 @@ connection default;
disconnect conn1;
drop table t;
+source include/wait_until_count_sessions.inc;
diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result b/storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result
index 13b5915354f..3f742690bd8 100644
--- a/storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result
+++ b/storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result
@@ -53,8 +53,6 @@ Variable_name Value
Slave_open_temp_tables 0
### Continue backup
SET DEBUG_SYNC = "now SIGNAL ttlss_continue";
-## Reset debug_sync points
-SET DEBUG_SYNC = "RESET";
### Wait for backup finish
include/filter_file.inc
### Slave tokubackup_slave_info content:
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc
index e0732ee63fc..9b795008eff 100644
--- a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc
@@ -59,9 +59,6 @@ SHOW STATUS LIKE 'Slave_open_temp_tables';
--echo ### Continue backup
SET DEBUG_SYNC = "now SIGNAL ttlss_continue";
---echo ## Reset debug_sync points
-SET DEBUG_SYNC = "RESET";
-
--connection slave_2
--echo ### Wait for backup finish
--reap
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/include/rpl_tokudb_row_img_general_loop.inc b/storage/tokudb/mysql-test/tokudb_rpl/include/rpl_tokudb_row_img_general_loop.inc
new file mode 100644
index 00000000000..321f09353a1
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/include/rpl_tokudb_row_img_general_loop.inc
@@ -0,0 +1,42 @@
+#
+# This is a helper script for rpl_row_img.test. It creates
+# all combinations MyISAM / InnoDB in a three server replication
+# chain. Each engine combination is tested against the current
+# seetings for binlog_row_image (on each server).
+#
+# The test script that is executed on every combination is the
+# only argument to this wrapper script. See below.
+#
+# This script takes one parameter:
+# - $row_img_test_script
+# the name of the test script to include in every combination
+#
+# Sample usage:
+# -- let $row_img_test_script= extra/rpl_tests/rpl_row_img.test
+# -- source include/rpl_row_img_general_loop.test
+
+
+-- let $engine_type_a= 2
+-- let $server_1_engine= TokuDB
+while($engine_type_a)
+{
+ -- let $engine_type_b= 2
+ -- let $server_2_engine= TokuDB
+ while($engine_type_b)
+ {
+ -- let $engine_type_c= 2
+ -- let $server_3_engine= TokuDB
+ while($engine_type_c)
+ {
+ -- echo ### engines: $server_1_engine, $server_2_engine, $server_3_engine
+ -- source $row_img_test_script
+
+ -- let $server_3_engine= InnoDB
+ -- dec $engine_type_c
+ }
+ -- let $server_2_engine= InnoDB
+ -- dec $engine_type_b
+ }
+ -- let $server_1_engine= InnoDB
+ -- dec $engine_type_a
+}
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_not_null_tokudb.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_not_null_tokudb.result
index 59bd2585395..ca044213a31 100644
--- a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_not_null_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_not_null_tokudb.result
@@ -6,25 +6,25 @@ Note #### Storing MySQL user name or password information in the master info rep
SET SQL_LOG_BIN= 0;
CREATE TABLE t1(`a` INT, `b` DATE DEFAULT NULL,
`c` INT DEFAULT NULL,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
CREATE TABLE t2(`a` INT, `b` DATE DEFAULT NULL,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
CREATE TABLE t3(`a` INT, `b` DATE DEFAULT NULL,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
CREATE TABLE t4(`a` INT, `b` DATE DEFAULT NULL,
`c` INT DEFAULT NULL,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
SET SQL_LOG_BIN= 1;
CREATE TABLE t1(`a` INT, `b` DATE DEFAULT NULL,
`c` INT DEFAULT NULL,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
CREATE TABLE t2(`a` INT, `b` DATE DEFAULT NULL,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
CREATE TABLE t3(`a` INT, `b` DATE DEFAULT '0000-00-00',
`c` INT DEFAULT 500,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
CREATE TABLE t4(`a` INT, `b` DATE DEFAULT '0000-00-00',
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
************* EXECUTION WITH INSERTS *************
INSERT INTO t1(a,b,c) VALUES (1, null, 1);
INSERT INTO t1(a,b,c) VALUES (2,'1111-11-11', 2);
@@ -90,10 +90,10 @@ DROP TABLE t4;
include/sync_slave_sql_with_master.inc
SET SQL_LOG_BIN= 0;
CREATE TABLE t1 (`a` INT, `b` BIT DEFAULT NULL, `c` BIT DEFAULT NULL,
-PRIMARY KEY (`a`)) ENGINE= Innodb;
+PRIMARY KEY (`a`)) ENGINE= TokuDB;
SET SQL_LOG_BIN= 1;
CREATE TABLE t1 (`a` INT, `b` BIT DEFAULT b'01', `c` BIT DEFAULT NULL,
-PRIMARY KEY (`a`)) ENGINE= Innodb;
+PRIMARY KEY (`a`)) ENGINE= TokuDB;
************* EXECUTION WITH INSERTS *************
INSERT INTO t1(a,b,c) VALUES (1, null, b'01');
INSERT INTO t1(a,b,c) VALUES (2,b'00', b'01');
@@ -138,21 +138,21 @@ include/sync_slave_sql_with_master.inc
################################################################################
SET SQL_LOG_BIN= 0;
CREATE TABLE t1(`a` INT NOT NULL, `b` INT,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
CREATE TABLE t2(`a` INT NOT NULL, `b` INT,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
CREATE TABLE t3(`a` INT NOT NULL, `b` INT,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
SET SQL_LOG_BIN= 1;
CREATE TABLE t1(`a` INT NOT NULL, `b` INT NOT NULL,
`c` INT NOT NULL,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
CREATE TABLE t2(`a` INT NOT NULL, `b` INT NOT NULL,
`c` INT,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
CREATE TABLE t3(`a` INT NOT NULL, `b` INT NOT NULL,
`c` INT DEFAULT 500,
-PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1;
+PRIMARY KEY(`a`)) ENGINE=TokuDB DEFAULT CHARSET=LATIN1;
************* EXECUTION WITH INSERTS *************
INSERT INTO t1(a) VALUES (1);
INSERT INTO t1(a, b) VALUES (2, NULL);
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_basic_3tokudb.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_basic_3tokudb.result
index 5bff2ac389e..62714d1031c 100644
--- a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_basic_3tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_basic_3tokudb.result
@@ -3,7 +3,7 @@ Warnings:
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
[connection master]
-CREATE TABLE t1 (C1 CHAR(1), C2 CHAR(1), INDEX (C1)) ENGINE = 'INNODB' ;
+CREATE TABLE t1 (C1 CHAR(1), C2 CHAR(1), INDEX (C1)) ENGINE = 'TokuDB' ;
SELECT * FROM t1;
C1 C2
include/sync_slave_sql_with_master.inc
@@ -74,7 +74,7 @@ A B
A I
X Y
X Z
-CREATE TABLE t2 (c1 INT, c12 char(1), c2 INT, PRIMARY KEY (c1)) ENGINE = 'INNODB' ;
+CREATE TABLE t2 (c1 INT, c12 char(1), c2 INT, PRIMARY KEY (c1)) ENGINE = 'TokuDB' ;
INSERT INTO t2
VALUES (1,'A',2), (2,'A',4), (3,'A',9), (4,'A',15), (5,'A',25),
(6,'A',35), (7,'A',50), (8,'A',64), (9,'A',81);
@@ -184,7 +184,7 @@ c1 c12 c2
7 A 49
9 A 81
UPDATE t2 SET c12='X';
-CREATE TABLE t3 (C1 CHAR(1), C2 CHAR(1), pk1 INT, C3 CHAR(1), pk2 INT, PRIMARY KEY (pk1,pk2)) ENGINE = 'INNODB' ;
+CREATE TABLE t3 (C1 CHAR(1), C2 CHAR(1), pk1 INT, C3 CHAR(1), pk2 INT, PRIMARY KEY (pk1,pk2)) ENGINE = 'TokuDB' ;
INSERT INTO t3 VALUES ('A','B',1,'B',1), ('X','Y',2,'B',1), ('X','X',3,'B',1);
INSERT INTO t3 VALUES ('A','C',1,'B',2), ('X','Z',2,'B',2), ('A','A',3,'B',2);
SELECT * FROM t3 ORDER BY C1,C2;
@@ -232,7 +232,7 @@ A B 1 B 1
A I 1 B 2
X Y 2 B 1
X Z 2 B 2
-CREATE TABLE t6 (C1 CHAR(1), C2 CHAR(1), C3 INT) ENGINE = 'INNODB' ;
+CREATE TABLE t6 (C1 CHAR(1), C2 CHAR(1), C3 INT) ENGINE = 'TokuDB';
INSERT INTO t6 VALUES ('A','B',1), ('X','Y',2), ('X','X',3);
INSERT INTO t6 VALUES ('A','C',4), ('X','Z',5), ('A','A',6);
SELECT * FROM t6 ORDER BY C3;
@@ -280,7 +280,7 @@ A B 1
X Y 2
A I 4
X Z 5
-CREATE TABLE t5 (C1 CHAR(1), C2 CHAR(1), C3 INT PRIMARY KEY) ENGINE = 'INNODB' ;
+CREATE TABLE t5 (C1 CHAR(1), C2 CHAR(1), C3 INT PRIMARY KEY) ENGINE = 'TokuDB' ;
INSERT INTO t5 VALUES ('A','B',1), ('X','Y',2), ('X','X',3);
INSERT INTO t5 VALUES ('A','C',4), ('X','Z',5), ('A','A',6);
UPDATE t5,t2,t3 SET t5.C2='Q', t2.c12='R', t3.C3 ='S' WHERE t5.C1 = t2.c12 AND t5.C1 = t3.C1;
@@ -375,7 +375,7 @@ X Q 5 9 R 81 X Y 2 S 1
X Q 5 9 R 81 X Z 2 S 2
SET @saved_slave_type_conversions = @@SLAVE_TYPE_CONVERSIONS;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY';
-CREATE TABLE t4 (C1 CHAR(1) PRIMARY KEY, B1 BIT(1), B2 BIT(1) NOT NULL DEFAULT 0, C2 CHAR(1) NOT NULL DEFAULT 'A') ENGINE = 'INNODB' ;
+CREATE TABLE t4 (C1 CHAR(1) PRIMARY KEY, B1 BIT(1), B2 BIT(1) NOT NULL DEFAULT 0, C2 CHAR(1) NOT NULL DEFAULT 'A') ENGINE = 'TokuDB' ;
INSERT INTO t4 SET C1 = 1;
SELECT C1,HEX(B1),HEX(B2) FROM t4 ORDER BY C1;
C1 HEX(B1) HEX(B2)
@@ -385,7 +385,7 @@ SELECT C1,HEX(B1),HEX(B2) FROM t4 ORDER BY C1;
C1 HEX(B1) HEX(B2)
1 NULL 0
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
-CREATE TABLE t7 (C1 INT PRIMARY KEY, C2 INT) ENGINE = 'INNODB' ;
+CREATE TABLE t7 (C1 INT PRIMARY KEY, C2 INT) ENGINE = 'TokuDB' ;
include/sync_slave_sql_with_master.inc
--- on slave: original values ---
INSERT INTO t7 VALUES (1,3), (2,6), (3,9);
@@ -411,7 +411,7 @@ C1 C2
2 4
3 6
--- on master ---
-CREATE TABLE t8 (a INT PRIMARY KEY, b INT UNIQUE, c INT UNIQUE) ENGINE = 'INNODB' ;
+CREATE TABLE t8 (a INT PRIMARY KEY, b INT UNIQUE, c INT UNIQUE) ENGINE = 'TokuDB' ;
INSERT INTO t8 VALUES (99,99,99);
INSERT INTO t8 VALUES (99,22,33);
ERROR 23000: Duplicate entry '99' for key 'PRIMARY'
@@ -480,33 +480,33 @@ DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8;
include/sync_slave_sql_with_master.inc
CREATE TABLE t1 (i INT NOT NULL,
c CHAR(16) CHARACTER SET utf8 NOT NULL,
-j INT NOT NULL) ENGINE = 'INNODB' ;
+j INT NOT NULL) ENGINE = 'TokuDB' ;
CREATE TABLE t2 (i INT NOT NULL,
c CHAR(16) CHARACTER SET utf8 NOT NULL,
-j INT NOT NULL) ENGINE = 'INNODB' ;
+j INT NOT NULL) ENGINE = 'TokuDB' ;
include/sync_slave_sql_with_master.inc
ALTER TABLE t2 MODIFY c CHAR(128) CHARACTER SET utf8 NOT NULL;
CREATE TABLE t3 (i INT NOT NULL,
c CHAR(128) CHARACTER SET utf8 NOT NULL,
-j INT NOT NULL) ENGINE = 'INNODB' ;
+j INT NOT NULL) ENGINE = 'TokuDB' ;
include/sync_slave_sql_with_master.inc
ALTER TABLE t3 MODIFY c CHAR(16) CHARACTER SET utf8 NOT NULL;
CREATE TABLE t4 (i INT NOT NULL,
c CHAR(128) CHARACTER SET utf8 NOT NULL,
-j INT NOT NULL) ENGINE = 'INNODB' ;
+j INT NOT NULL) ENGINE = 'TokuDB' ;
CREATE TABLE t5 (i INT NOT NULL,
c CHAR(255) CHARACTER SET utf8 NOT NULL,
-j INT NOT NULL) ENGINE = 'INNODB' ;
+j INT NOT NULL) ENGINE = 'TokuDB' ;
include/sync_slave_sql_with_master.inc
ALTER TABLE t5 MODIFY c CHAR(16) CHARACTER SET utf8 NOT NULL;
CREATE TABLE t6 (i INT NOT NULL,
c CHAR(255) CHARACTER SET utf8 NOT NULL,
-j INT NOT NULL) ENGINE = 'INNODB' ;
+j INT NOT NULL) ENGINE = 'TokuDB' ;
include/sync_slave_sql_with_master.inc
ALTER TABLE t6 MODIFY c CHAR(128) CHARACTER SET utf8 NOT NULL;
CREATE TABLE t7 (i INT NOT NULL,
c CHAR(255) CHARACTER SET utf8 NOT NULL,
-j INT NOT NULL) ENGINE = 'INNODB' ;
+j INT NOT NULL) ENGINE = 'TokuDB' ;
SET @saved_slave_type_conversions = @@slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
[expecting slave to replicate correctly]
@@ -547,7 +547,7 @@ include/sync_slave_sql_with_master.inc
include/diff_tables.inc [master:t7, slave:t7]
drop table t1, t2, t3, t4, t5, t6, t7;
include/sync_slave_sql_with_master.inc
-CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE='INNODB' ;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE='TokuDB';
INSERT INTO t1 VALUES (1), (2), (3);
UPDATE t1 SET a = 10;
ERROR 23000: Duplicate entry '10' for key 'PRIMARY'
@@ -575,7 +575,7 @@ KEY `date_key` (`date_key`),
KEY `time_key` (`time_key`),
KEY `datetime_key` (`datetime_key`),
KEY `varchar_key` (`varchar_key`)
-) ENGINE='INNODB' ;
+) ENGINE='TokuDB';
INSERT INTO t1 VALUES (1,8,5,'0000-00-00','0000-00-00','10:37:38','10:37:38','0000-00-00 00:00:00','0000-00-00 00:00:00','p','p'),(2,0,9,'0000-00-00','0000-00-00','00:00:00','00:00:00','2007-10-14 00:00:00','2007-10-14 00:00:00','d','d');
CREATE TABLE t2 (
`pk` int(11) NOT NULL AUTO_INCREMENT,
@@ -595,7 +595,7 @@ KEY `date_key` (`date_key`),
KEY `time_key` (`time_key`),
KEY `datetime_key` (`datetime_key`),
KEY `varchar_key` (`varchar_key`)
-) ENGINE='INNODB' ;
+) ENGINE='TokuDB';
INSERT INTO t2 VALUES (1,1,6,'2005-12-23','2005-12-23','02:24:28','02:24:28','0000-00-00 00:00:00','0000-00-00 00:00:00','g','g'),(2,0,3,'2009-09-14','2009-09-14','00:00:00','00:00:00','2000-01-30 16:39:40','2000-01-30 16:39:40','q','q'),(3,0,3,'0000-00-00','0000-00-00','00:00:00','00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','c','c'),(4,1,6,'2007-03-29','2007-03-29','15:49:00','15:49:00','0000-00-00 00:00:00','0000-00-00 00:00:00','m','m'),(5,4,0,'2002-12-04','2002-12-04','00:00:00','00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','o','o'),(6,9,0,'2005-01-28','2005-01-28','00:00:00','00:00:00','2001-05-18 00:00:00','2001-05-18 00:00:00','w','w'),(7,6,0,'0000-00-00','0000-00-00','06:57:25','06:57:25','0000-00-00 00:00:00','0000-00-00 00:00:00','m','m'),(8,0,0,'0000-00-00','0000-00-00','00:00:00','00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','z','z'),(9,4,6,'2006-08-15','2006-08-15','00:00:00','00:00:00','2002-04-12 14:44:25','2002-04-12 14:44:25','j','j'),(10,0,5,'2006-12-20','2006-12-20','10:13:53','10:13:53','2008-07-22 00:00:00','2008-07-22 00:00:00','y','y'),(11,9,7,'0000-00-00','0000-00-00','00:00:00','00:00:00','2004-07-05 00:00:00','2004-07-05 00:00:00','{','{'),(12,4,3,'2007-01-26','2007-01-26','23:00:51','23:00:51','2001-05-16 00:00:00','2001-05-16 00:00:00','f','f'),(13,7,0,'2004-03-27','2004-03-27','00:00:00','00:00:00','2005-01-24 03:30:37','2005-01-24 03:30:37','',''),(14,6,0,'2006-07-26','2006-07-26','18:43:57','18:43:57','0000-00-00 00:00:00','0000-00-00 00:00:00','{','{'),(15,0,6,'2000-01-14','2000-01-14','00:00:00','00:00:00','2000-09-21 00:00:00','2000-09-21 00:00:00','o','o'),(16,9,8,'0000-00-00','0000-00-00','21:15:08','21:15:08','0000-00-00 00:00:00','0000-00-00 00:00:00','a','a'),(17,2,0,'2004-10-27','2004-10-27','00:00:00','00:00:00','2004-03-24 22:13:43','2004-03-24 22:13:43','',''),(18,7,4,'0000-00-00','0000-00-00','08:38:27','08:38:27','2002-03-18 19:51:44','2002-03-18 19:51:44','t','t'),(19,5,3,'2008-03-07','2008-03-07','03:29:07','03:29:07','2007-12-01 18:44:44','2007-12-01 18:44:44','t','t'),(20,0,0,'2002-04-09','2002-04-09','16:06:03','16:06:03','2009-04-22 00:00:00','2009-04-22 00:00:00','n','n');
DELETE FROM t2 WHERE `int_key` < 3 LIMIT 1;
UPDATE t1 SET `int_key` = 3 ORDER BY `pk` LIMIT 4;
@@ -612,7 +612,7 @@ include/sync_slave_sql_with_master.inc
include/diff_tables.inc [master:t2, slave:t2]
DROP TABLE t1, t2;
EOF OF TESTS
-CREATE TABLE t1 (a int) ENGINE='INNODB' ;
+CREATE TABLE t1 (a int) ENGINE='TokuDB';
INSERT IGNORE INTO t1 VALUES (NULL);
INSERT INTO t1 ( a ) VALUES ( 0 );
INSERT INTO t1 ( a ) VALUES ( 9 );
@@ -631,7 +631,7 @@ drop table t1;
include/sync_slave_sql_with_master.inc
SET @saved_slave_type_conversions = @@SLAVE_TYPE_CONVERSIONS;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY';
-CREATE TABLE t1 (a bit) ENGINE='INNODB' ;
+CREATE TABLE t1 (a bit) ENGINE='TokuDB';
INSERT IGNORE INTO t1 VALUES (NULL);
INSERT INTO t1 ( a ) VALUES ( 0 );
UPDATE t1 SET a = 0 WHERE a = 1 LIMIT 3;
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_commit_after_flush.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_commit_after_flush.result
new file mode 100644
index 00000000000..2aeef4204f5
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_commit_after_flush.result
@@ -0,0 +1,15 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+CREATE TABLE t1 (a INT) ENGINE=tokudb;
+begin;
+insert into t1 values(1);
+flush tables with read lock;
+commit;
+include/sync_slave_sql_with_master.inc
+unlock tables;
+drop table t1;
+include/sync_slave_sql_with_master.inc
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id.result
new file mode 100644
index 00000000000..217520a59d4
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id.result
@@ -0,0 +1,554 @@
+#
+# Setup
+#
+#
+# See if queries that use both auto_increment and LAST_INSERT_ID()
+# are replicated well
+#
+# We also check how the foreign_key_check variable is replicated
+#
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+SET @old_concurrent_insert= @@global.concurrent_insert;
+SET @@global.concurrent_insert= 0;
+create table t1(a int auto_increment, key(a)) engine=tokudb;
+create table t2(b int auto_increment, c int, key(b)) engine=tokudb;
+insert into t1 values (1),(2),(3);
+insert into t1 values (null);
+insert into t2 values (null,last_insert_id());
+include/sync_slave_sql_with_master.inc
+select * from t1 ORDER BY a;
+a
+1
+2
+3
+4
+select * from t2 ORDER BY b;
+b c
+1 4
+drop table t1;
+drop table t2;
+create table t1(a int auto_increment, key(a)) engine=tokudb;
+create table t2(b int auto_increment, c int, key(b), foreign key(b) references t1(a)) engine=tokudb;
+SET FOREIGN_KEY_CHECKS=0;
+insert into t1 values (10);
+insert into t1 values (null),(null),(null);
+insert into t2 values (5,0);
+insert into t2 values (null,last_insert_id());
+SET FOREIGN_KEY_CHECKS=1;
+include/sync_slave_sql_with_master.inc
+select * from t1;
+a
+10
+11
+12
+13
+select * from t2;
+b c
+5 0
+6 11
+#
+# check if INSERT SELECT in auto_increment is well replicated (bug #490)
+#
+drop table t2;
+drop table t1;
+create table t1(a int auto_increment, key(a)) engine=tokudb;
+create table t2(b int auto_increment, c int, key(b)) engine=tokudb;
+insert into t1 values (10);
+insert into t1 values (null),(null),(null);
+insert into t2 values (5,0);
+insert into t2 (c) select * from t1 ORDER BY a;
+select * from t2 ORDER BY b;
+b c
+5 0
+6 10
+7 11
+8 12
+9 13
+include/sync_slave_sql_with_master.inc
+select * from t1 ORDER BY a;
+a
+10
+11
+12
+13
+select * from t2 ORDER BY b;
+b c
+5 0
+6 10
+7 11
+8 12
+9 13
+drop table t1;
+drop table t2;
+include/sync_slave_sql_with_master.inc
+#
+# Bug#8412: Error codes reported in binary log for CHARACTER SET,
+# FOREIGN_KEY_CHECKS
+#
+SET TIMESTAMP=1000000000;
+CREATE TABLE t1 ( a INT UNIQUE ) engine=tokudb;
+SET FOREIGN_KEY_CHECKS=0;
+INSERT INTO t1 VALUES (1),(1);
+Got one of the listed errors
+include/sync_slave_sql_with_master.inc
+drop table t1;
+include/sync_slave_sql_with_master.inc
+#
+# Bug#14553: NULL in WHERE resets LAST_INSERT_ID
+#
+set @@session.sql_auto_is_null=1;
+create table t1(a int auto_increment, key(a)) engine=tokudb;
+create table t2(a int) engine=tokudb;
+insert into t1 (a) values (null);
+insert into t2 (a) select a from t1 where a is null;
+insert into t2 (a) select a from t1 where a is null;
+select * from t2;
+a
+1
+include/sync_slave_sql_with_master.inc
+select * from t2;
+a
+1
+drop table t1;
+drop table t2;
+#
+# End of 4.1 tests
+#
+#
+# BUG#15728: LAST_INSERT_ID function inside a stored function returns 0
+#
+# The solution is not to reset last_insert_id on enter to sub-statement.
+#
+drop function if exists bug15728;
+drop function if exists bug15728_insert;
+drop table if exists t1, t2;
+create table t1 (
+id int not null auto_increment,
+last_id int,
+primary key (id)
+) engine=tokudb;
+create function bug15728() returns int(11)
+return last_insert_id();
+insert into t1 (last_id) values (0);
+insert into t1 (last_id) values (last_insert_id());
+insert into t1 (last_id) values (bug15728());
+create table t2 (
+id int not null auto_increment,
+last_id int,
+primary key (id)
+) engine=tokudb;
+create function bug15728_insert() returns int(11) modifies sql data
+begin
+insert into t2 (last_id) values (bug15728());
+return bug15728();
+end|
+create trigger t1_bi before insert on t1 for each row
+begin
+declare res int;
+select bug15728_insert() into res;
+set NEW.last_id = res;
+end|
+insert into t1 (last_id) values (0);
+drop trigger t1_bi;
+select last_insert_id();
+last_insert_id()
+4
+select bug15728_insert();
+bug15728_insert()
+2
+select last_insert_id();
+last_insert_id()
+4
+insert into t1 (last_id) values (bug15728());
+select last_insert_id();
+last_insert_id()
+5
+drop procedure if exists foo;
+create procedure foo()
+begin
+declare res int;
+insert into t2 (last_id) values (bug15728());
+insert into t1 (last_id) values (bug15728());
+end|
+call foo();
+select * from t1;
+id last_id
+1 0
+2 1
+3 2
+4 1
+5 4
+6 3
+select * from t2;
+id last_id
+1 3
+2 4
+3 5
+include/sync_slave_sql_with_master.inc
+select * from t1;
+id last_id
+1 0
+2 1
+3 2
+4 1
+5 4
+6 3
+select * from t2;
+id last_id
+1 3
+2 4
+3 5
+drop function bug15728;
+drop function bug15728_insert;
+drop table t1,t2;
+drop procedure foo;
+create table t1 (n int primary key auto_increment not null,
+b int, unique(b)) engine=tokudb;
+set sql_log_bin=0;
+insert into t1 values(null,100);
+replace into t1 values(null,50),(null,100),(null,150);
+select * from t1 order by n;
+n b
+2 50
+3 100
+4 150
+truncate table t1;
+set sql_log_bin=1;
+insert into t1 values(null,100);
+select * from t1 order by n;
+n b
+1 100
+include/sync_slave_sql_with_master.inc
+insert into t1 values(null,200),(null,300);
+delete from t1 where b <> 100;
+select * from t1 order by n;
+n b
+1 100
+replace into t1 values(null,100),(null,350);
+select * from t1 order by n;
+n b
+2 100
+3 350
+include/sync_slave_sql_with_master.inc
+select * from t1 order by n;
+n b
+2 100
+3 350
+insert into t1 values (NULL,400),(3,500),(NULL,600) on duplicate key UPDATE n=1000;
+select * from t1 order by n;
+n b
+2 100
+4 400
+5 600
+1000 350
+include/sync_slave_sql_with_master.inc
+select * from t1 order by n;
+n b
+2 100
+4 400
+5 600
+1000 350
+drop table t1;
+create table t1 (n int primary key auto_increment not null,
+b int, unique(b)) engine=tokudb;
+insert into t1 values(null,100);
+select * from t1 order by n;
+n b
+1 100
+include/sync_slave_sql_with_master.inc
+insert into t1 values(null,200),(null,300);
+delete from t1 where b <> 100;
+select * from t1 order by n;
+n b
+1 100
+insert into t1 values(null,100),(null,350) on duplicate key update n=2;
+select * from t1 order by n;
+n b
+2 100
+3 350
+include/sync_slave_sql_with_master.inc
+select * from t1 order by n;
+n b
+2 100
+3 350
+drop table t1;
+include/sync_slave_sql_with_master.inc
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b INT,
+UNIQUE(b)) ENGINE=tokudb;
+INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10;
+SELECT * FROM t1 ORDER BY a;
+a b
+1 10
+2 2
+include/sync_slave_sql_with_master.inc
+SELECT * FROM t1 ORDER BY a;
+a b
+1 10
+2 2
+drop table t1;
+CREATE TABLE t1 (
+id bigint(20) unsigned NOT NULL auto_increment,
+field_1 int(10) unsigned NOT NULL,
+field_2 varchar(255) NOT NULL,
+field_3 varchar(255) NOT NULL,
+PRIMARY KEY (id),
+UNIQUE KEY field_1 (field_1, field_2)
+) ENGINE=tokudb;
+CREATE TABLE t2 (
+field_a int(10) unsigned NOT NULL,
+field_b varchar(255) NOT NULL,
+field_c varchar(255) NOT NULL
+) ENGINE=tokudb;
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (1, 'a', '1a');
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (2, 'b', '2b');
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (3, 'c', '3c');
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (4, 'd', '4d');
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (5, 'e', '5e');
+INSERT INTO t1 (field_1, field_2, field_3)
+SELECT t2.field_a, t2.field_b, t2.field_c
+FROM t2
+ON DUPLICATE KEY UPDATE
+t1.field_3 = t2.field_c;
+INSERT INTO t2 (field_a, field_b, field_c) VALUES (6, 'f', '6f');
+INSERT INTO t1 (field_1, field_2, field_3)
+SELECT t2.field_a, t2.field_b, t2.field_c
+FROM t2
+ON DUPLICATE KEY UPDATE
+t1.field_3 = t2.field_c;
+SELECT * FROM t1 ORDER BY id;
+id field_1 field_2 field_3
+1 1 a 1a
+2 2 b 2b
+3 3 c 3c
+4 4 d 4d
+5 5 e 5e
+8 6 f 6f
+include/sync_slave_sql_with_master.inc
+SELECT * FROM t1 ORDER BY id;
+id field_1 field_2 field_3
+1 1 a 1a
+2 2 b 2b
+3 3 c 3c
+4 4 d 4d
+5 5 e 5e
+8 6 f 6f
+drop table t1, t2;
+DROP PROCEDURE IF EXISTS p1;
+DROP TABLE IF EXISTS t1, t2;
+SELECT LAST_INSERT_ID(0);
+LAST_INSERT_ID(0)
+0
+CREATE TABLE t1 (
+id INT NOT NULL DEFAULT 0,
+last_id INT,
+PRIMARY KEY (id)
+) ENGINE=tokudb;
+CREATE TABLE t2 (
+id INT NOT NULL AUTO_INCREMENT,
+last_id INT,
+PRIMARY KEY (id)
+) ENGINE=tokudb;
+CREATE PROCEDURE p1()
+BEGIN
+INSERT INTO t2 (last_id) VALUES (LAST_INSERT_ID());
+INSERT INTO t1 (last_id) VALUES (LAST_INSERT_ID());
+END|
+CALL p1();
+SELECT * FROM t1 ORDER BY id;
+id last_id
+0 1
+SELECT * FROM t2 ORDER BY id;
+id last_id
+1 0
+include/sync_slave_sql_with_master.inc
+SELECT * FROM t1 ORDER BY id;
+id last_id
+0 1
+SELECT * FROM t2 ORDER BY id;
+id last_id
+1 0
+DROP PROCEDURE p1;
+DROP TABLE t1, t2;
+DROP PROCEDURE IF EXISTS p1;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP FUNCTION IF EXISTS f3;
+DROP TABLE IF EXISTS t1, t2;
+CREATE TABLE t1 (
+i INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+j INT DEFAULT 0
+) ENGINE=tokudb;
+CREATE TABLE t2 (i INT) ENGINE=tokudb;
+CREATE PROCEDURE p1()
+BEGIN
+INSERT INTO t1 (i) VALUES (NULL);
+INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
+INSERT INTO t1 (i) VALUES (NULL), (NULL);
+INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
+END |
+CREATE FUNCTION f1() RETURNS INT MODIFIES SQL DATA
+BEGIN
+INSERT INTO t1 (i) VALUES (NULL);
+INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
+INSERT INTO t1 (i) VALUES (NULL), (NULL);
+INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
+RETURN 0;
+END |
+CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC
+RETURN LAST_INSERT_ID() |
+CREATE FUNCTION f3() RETURNS INT MODIFIES SQL DATA
+BEGIN
+INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
+RETURN 0;
+END |
+INSERT INTO t1 VALUES (NULL, -1);
+CALL p1();
+SELECT f1();
+f1()
+0
+INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()),
+(NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2());
+INSERT INTO t1 VALUES (NULL, f2());
+INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID());
+UPDATE t1 SET j= -1 WHERE i IS NULL;
+INSERT INTO t1 (i) VALUES (NULL);
+INSERT INTO t1 (i) VALUES (NULL);
+SELECT f3();
+f3()
+0
+SELECT * FROM t1 ORDER BY i;
+i j
+1 -1
+2 0
+3 0
+4 0
+5 0
+6 0
+7 0
+8 3
+9 3
+10 3
+11 3
+12 3
+13 8
+14 -1
+15 13
+16 0
+17 0
+SELECT * FROM t2 ORDER BY i;
+i
+2
+3
+5
+6
+16
+include/sync_slave_sql_with_master.inc
+SELECT * FROM t1;
+i j
+1 -1
+2 0
+3 0
+4 0
+5 0
+6 0
+7 0
+8 3
+9 3
+10 3
+11 3
+12 3
+13 8
+14 -1
+15 13
+16 0
+17 0
+SELECT * FROM t2;
+i
+2
+3
+5
+6
+16
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP FUNCTION f3;
+DROP TABLE t1, t2;
+include/sync_slave_sql_with_master.inc
+#
+# End of 5.0 tests
+#
+create table t2 (
+id int not null auto_increment,
+last_id int,
+primary key (id)
+) engine=tokudb;
+truncate table t2;
+create table t1 (id tinyint primary key) engine=tokudb;
+create function insid() returns int
+begin
+insert into t2 (last_id) values (0);
+return 0;
+end|
+set sql_log_bin=0;
+insert into t2 (id) values(1),(2),(3);
+delete from t2;
+set sql_log_bin=1;
+select insid();
+insid()
+0
+set sql_log_bin=0;
+insert into t2 (id) values(5),(6),(7);
+delete from t2 where id>=5;
+set sql_log_bin=1;
+insert into t1 select insid();
+select * from t1 order by id;
+id
+0
+select * from t2 order by id;
+id last_id
+4 0
+8 0
+include/sync_slave_sql_with_master.inc
+select * from t1 order by id;
+id
+0
+select * from t2 order by id;
+id last_id
+4 0
+8 0
+drop table t1;
+drop function insid;
+truncate table t2;
+create table t1 (n int primary key auto_increment not null,
+b int, unique(b)) engine=tokudb;
+create procedure foo()
+begin
+insert into t1 values(null,10);
+insert ignore into t1 values(null,10);
+insert ignore into t1 values(null,10);
+insert into t2 values(null,3);
+end|
+call foo();
+select * from t1 order by n;
+n b
+1 10
+select * from t2 order by id;
+id last_id
+1 3
+include/sync_slave_sql_with_master.inc
+select * from t1 order by n;
+n b
+1 10
+select * from t2 order by id;
+id last_id
+1 3
+drop table t1, t2;
+drop procedure foo;
+SET @@global.concurrent_insert= @old_concurrent_insert;
+set @@session.sql_auto_is_null=default;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id_pk.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id_pk.result
new file mode 100644
index 00000000000..cce5d6d42e6
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id_pk.result
@@ -0,0 +1,82 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.");
+create table t1(a int auto_increment, primary key(a));
+create table t2(b int auto_increment, c int, primary key(b));
+insert into t1 values (1),(2),(3);
+insert into t1 values (null);
+insert into t2 values (null,last_insert_id());
+include/sync_slave_sql_with_master.inc
+select * from t1 ORDER BY a;
+a
+1
+2
+3
+4
+select * from t2 ORDER BY b;
+b c
+1 4
+drop table t1;
+drop table t2;
+create table t1(a int auto_increment, key(a)) engine=tokudb;
+create table t2(b int auto_increment, c int, key(b), foreign key(b) references t1(a)) engine=tokudb;
+SET FOREIGN_KEY_CHECKS=0;
+insert into t1 values (10);
+insert into t1 values (null),(null),(null);
+insert into t2 values (5,0);
+insert into t2 values (null,last_insert_id());
+SET FOREIGN_KEY_CHECKS=1;
+include/sync_slave_sql_with_master.inc
+select * from t1;
+a
+10
+11
+12
+13
+select * from t2;
+b c
+5 0
+6 11
+drop table t2;
+drop table t1;
+create table t1(a int auto_increment, primary key(a));
+create table t2(b int auto_increment, c int, primary key(b));
+insert into t1 values (10);
+insert into t1 values (null),(null),(null);
+insert into t2 values (5,0);
+insert into t2 (c) select * from t1 ORDER BY a;
+select * from t2 ORDER BY b;
+b c
+5 0
+6 10
+7 11
+8 12
+9 13
+include/sync_slave_sql_with_master.inc
+select * from t1 ORDER BY a;
+a
+10
+11
+12
+13
+select * from t2 ORDER BY b;
+b c
+5 0
+6 10
+7 11
+8 12
+9 13
+drop table t1;
+drop table t2;
+include/sync_slave_sql_with_master.inc
+SET TIMESTAMP=1000000000;
+CREATE TABLE t1 ( a INT UNIQUE );
+SET FOREIGN_KEY_CHECKS=0;
+INSERT INTO t1 VALUES (1),(1);
+Got one of the listed errors
+include/sync_slave_sql_with_master.inc
+drop table t1;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update.result
new file mode 100644
index 00000000000..4ff45b46bd2
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update.result
@@ -0,0 +1,29 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.');
+CREATE TABLE t1 (
+a int unsigned not null auto_increment primary key,
+b int unsigned
+) ENGINE=TokuDB;
+CREATE TABLE t2 (
+a int unsigned not null auto_increment primary key,
+b int unsigned
+) ENGINE=TokuDB;
+INSERT INTO t1 VALUES (NULL, 0);
+INSERT INTO t1 SELECT NULL, 0 FROM t1;
+INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
+SELECT * FROM t1 ORDER BY a;
+a b
+1 0
+2 0
+SELECT * FROM t2 ORDER BY a;
+a b
+1 0
+2 1
+UPDATE t1, t2 SET t1.b = t2.b WHERE t1.a = t2.a;
+include/sync_slave_sql_with_master.inc
+drop table t1, t2;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update2.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update2.result
new file mode 100644
index 00000000000..d811ce42143
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update2.result
@@ -0,0 +1,60 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT');
+drop table if exists t1,t2;
+CREATE TABLE t1 (
+a int unsigned not null auto_increment primary key,
+b int unsigned
+) ENGINE=TokuDB;
+CREATE TABLE t2 (
+a int unsigned not null auto_increment primary key,
+b int unsigned
+) ENGINE=TokuDB;
+INSERT INTO t1 VALUES (NULL, 0);
+INSERT INTO t1 SELECT NULL, 0 FROM t1;
+INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
+SELECT * FROM t1 ORDER BY a;
+a b
+1 0
+2 0
+SELECT * FROM t2 ORDER BY a;
+a b
+1 0
+2 1
+UPDATE t1, t2 SET t1.b = (t2.b+4) WHERE t1.a = t2.a;
+SELECT * FROM t1 ORDER BY a;
+a b
+1 4
+2 5
+SELECT * FROM t2 ORDER BY a;
+a b
+1 0
+2 1
+SELECT * FROM t1 ORDER BY a;
+a b
+1 4
+2 5
+SELECT * FROM t2 ORDER BY a;
+a b
+1 0
+2 1
+drop table t1,t2;
+include/sync_slave_sql_with_master.inc
+reset master;
+RESET MASTER;
+CREATE TABLE t1 ( a INT );
+INSERT INTO t1 VALUES (0);
+UPDATE t1, (SELECT 3 as b) AS x SET t1.a = x.b;
+select * from t1;
+a
+3
+include/sync_slave_sql_with_master.inc
+select * from t1;
+a
+3
+drop table t1;
+include/sync_slave_sql_with_master.inc
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update3.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update3.result
new file mode 100644
index 00000000000..48de0f97072
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update3.result
@@ -0,0 +1,202 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.');
+
+-------- Test for BUG#9361 --------
+CREATE TABLE t1 (
+a int unsigned not null auto_increment primary key,
+b int unsigned
+) ENGINE=TokuDB;
+CREATE TABLE t2 (
+a int unsigned not null auto_increment primary key,
+b int unsigned
+) ENGINE=TokuDB;
+INSERT INTO t1 VALUES (NULL, 0);
+INSERT INTO t1 SELECT NULL, 0 FROM t1;
+INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
+SELECT * FROM t1 ORDER BY a;
+a b
+1 0
+2 0
+SELECT * FROM t2 ORDER BY a;
+a b
+1 0
+2 1
+UPDATE t2, (SELECT a FROM t1 ORDER BY a) AS t SET t2.b = t.a+5 ;
+SELECT * FROM t1 ORDER BY a;
+a b
+1 0
+2 0
+SELECT * FROM t2 ORDER BY a;
+a b
+1 6
+2 6
+include/sync_slave_sql_with_master.inc
+SELECT * FROM t1 ORDER BY a;
+a b
+1 0
+2 0
+SELECT * FROM t2 ORDER BY a;
+a b
+1 6
+2 6
+drop table t1,t2;
+
+-------- Test 1 for BUG#9361 --------
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+CREATE TABLE t1 (
+a1 char(30),
+a2 int,
+a3 int,
+a4 char(30),
+a5 char(30)
+);
+CREATE TABLE t2 (
+b1 int,
+b2 char(30)
+);
+INSERT INTO t1 VALUES ('Yes', 1, NULL, 'foo', 'bar');
+INSERT INTO t2 VALUES (1, 'baz');
+UPDATE t1 a, t2
+SET a.a1 = 'No'
+WHERE a.a2 =
+(SELECT b1
+FROM t2
+WHERE b2 = 'baz')
+AND a.a3 IS NULL
+AND a.a4 = 'foo'
+AND a.a5 = 'bar';
+include/sync_slave_sql_with_master.inc
+SELECT * FROM t1;
+a1 a2 a3 a4 a5
+No 1 NULL foo bar
+SELECT * FROM t2;
+b1 b2
+1 baz
+DROP TABLE t1, t2;
+
+-------- Test 2 for BUG#9361 --------
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
+CREATE TABLE t1 (
+i INT,
+j INT,
+x INT,
+y INT,
+z INT
+);
+CREATE TABLE t2 (
+i INT,
+k INT,
+x INT,
+y INT,
+z INT
+);
+CREATE TABLE t3 (
+j INT,
+k INT,
+x INT,
+y INT,
+z INT
+);
+INSERT INTO t1 VALUES ( 1, 2,13,14,15);
+INSERT INTO t2 VALUES ( 1, 3,23,24,25);
+INSERT INTO t3 VALUES ( 2, 3, 1,34,35), ( 2, 3, 1,34,36);
+UPDATE t1 AS a
+INNER JOIN t2 AS b
+ON a.i = b.i
+INNER JOIN t3 AS c
+ON a.j = c.j AND b.k = c.k
+SET a.x = b.x,
+a.y = b.y,
+a.z = (
+SELECT sum(z)
+FROM t3
+WHERE y = 34
+)
+WHERE b.x = 23;
+include/sync_slave_sql_with_master.inc
+SELECT * FROM t1;
+i j x y z
+1 2 23 24 71
+DROP TABLE t1, t2, t3;
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+DROP TABLE IF EXISTS t2;
+Warnings:
+Note 1051 Unknown table 'test.t2'
+CREATE TABLE t1 (
+idp int(11) NOT NULL default '0',
+idpro int(11) default NULL,
+price decimal(19,4) default NULL,
+PRIMARY KEY (idp)
+);
+CREATE TABLE t2 (
+idpro int(11) NOT NULL default '0',
+price decimal(19,4) default NULL,
+nbprice int(11) default NULL,
+PRIMARY KEY (idpro)
+);
+INSERT INTO t1 VALUES
+(1,1,'3.0000'),
+(2,2,'1.0000'),
+(3,1,'1.0000'),
+(4,1,'4.0000'),
+(5,3,'2.0000'),
+(6,2,'4.0000');
+INSERT INTO t2 VALUES
+(1,'0.0000',0),
+(2,'0.0000',0),
+(3,'0.0000',0);
+update
+t2
+join
+( select idpro, min(price) as min_price, count(*) as nbr_price
+from t1
+where idpro>0 and price>0
+group by idpro
+) as table_price
+on t2.idpro = table_price.idpro
+set t2.price = table_price.min_price,
+t2.nbprice = table_price.nbr_price;
+select "-- MASTER AFTER JOIN --" as "";
+
+-- MASTER AFTER JOIN --
+select * from t1;
+idp idpro price
+1 1 3.0000
+2 2 1.0000
+3 1 1.0000
+4 1 4.0000
+5 3 2.0000
+6 2 4.0000
+select * from t2;
+idpro price nbprice
+1 1.0000 3
+2 1.0000 2
+3 2.0000 1
+include/sync_slave_sql_with_master.inc
+select "-- SLAVE AFTER JOIN --" as "";
+
+-- SLAVE AFTER JOIN --
+select * from t1;
+idp idpro price
+1 1 3.0000
+2 2 1.0000
+3 1 1.0000
+4 1 4.0000
+5 3 2.0000
+6 2 4.0000
+select * from t2;
+idpro price nbprice
+1 1.0000 3
+2 1.0000 2
+3 2.0000 1
+DROP TABLE t1, t2;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_crash_safe.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_crash_safe.result
new file mode 100644
index 00000000000..04578c3ff68
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_crash_safe.result
@@ -0,0 +1,2183 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+call mtr.add_suppression('Attempting backtrace');
+call mtr.add_suppression("Recovery from master pos .* and file master-bin.000001");
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+call mtr.add_suppression(".* InnoDB: Warning: allocated tablespace .*, old maximum was .*");
+###################################################################################
+# PREPARE EXECUTION
+###################################################################################
+include/stop_slave.inc
+SHOW CREATE TABLE mysql.slave_relay_log_info;
+Table Create Table
+slave_relay_log_info CREATE TABLE `slave_relay_log_info` (
+ `Number_of_lines` int(10) unsigned NOT NULL COMMENT 'Number of lines in the file or rows in the table. Used to version table definitions.',
+ `Relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'The name of the current relay log file.',
+ `Relay_log_pos` bigint(20) unsigned NOT NULL COMMENT 'The relay log position of the last executed event.',
+ `Master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'The name of the master binary log file from which the events in the relay log file were read.',
+ `Master_log_pos` bigint(20) unsigned NOT NULL COMMENT 'The master log position of the last executed event.',
+ `Sql_delay` int(11) NOT NULL COMMENT 'The number of seconds that the slave must lag behind the master.',
+ `Number_of_workers` int(10) unsigned NOT NULL,
+ `Id` int(10) unsigned NOT NULL COMMENT 'Internal Id that uniquely identifies this record.',
+ PRIMARY KEY (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT='Relay Log Information'
+SHOW CREATE TABLE mysql.slave_worker_info;
+Table Create Table
+slave_worker_info CREATE TABLE `slave_worker_info` (
+ `Id` int(10) unsigned NOT NULL,
+ `Relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Relay_log_pos` bigint(20) unsigned NOT NULL,
+ `Master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Master_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Checkpoint_relay_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Checkpoint_master_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_seqno` int(10) unsigned NOT NULL,
+ `Checkpoint_group_size` int(10) unsigned NOT NULL,
+ `Checkpoint_group_bitmap` blob NOT NULL,
+ PRIMARY KEY (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT='Worker Information'
+ALTER TABLE mysql.slave_relay_log_info ENGINE= Innodb;
+ALTER TABLE mysql.slave_worker_info ENGINE= Innodb;
+SHOW CREATE TABLE mysql.slave_relay_log_info;
+Table Create Table
+slave_relay_log_info CREATE TABLE `slave_relay_log_info` (
+ `Number_of_lines` int(10) unsigned NOT NULL COMMENT 'Number of lines in the file or rows in the table. Used to version table definitions.',
+ `Relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'The name of the current relay log file.',
+ `Relay_log_pos` bigint(20) unsigned NOT NULL COMMENT 'The relay log position of the last executed event.',
+ `Master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'The name of the master binary log file from which the events in the relay log file were read.',
+ `Master_log_pos` bigint(20) unsigned NOT NULL COMMENT 'The master log position of the last executed event.',
+ `Sql_delay` int(11) NOT NULL COMMENT 'The number of seconds that the slave must lag behind the master.',
+ `Number_of_workers` int(10) unsigned NOT NULL,
+ `Id` int(10) unsigned NOT NULL COMMENT 'Internal Id that uniquely identifies this record.',
+ PRIMARY KEY (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT='Relay Log Information'
+SHOW CREATE TABLE mysql.slave_worker_info;
+Table Create Table
+slave_worker_info CREATE TABLE `slave_worker_info` (
+ `Id` int(10) unsigned NOT NULL,
+ `Relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Relay_log_pos` bigint(20) unsigned NOT NULL,
+ `Master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Master_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Checkpoint_relay_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Checkpoint_master_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_seqno` int(10) unsigned NOT NULL,
+ `Checkpoint_group_size` int(10) unsigned NOT NULL,
+ `Checkpoint_group_bitmap` blob NOT NULL,
+ PRIMARY KEY (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT='Worker Information'
+include/start_slave.inc
+rpl_mixing_engines.inc [commands=configure]
+CREATE TABLE nt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE nt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE nt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE nt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE nt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE nt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE tt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+CREATE TABLE tt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+CREATE TABLE tt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+CREATE TABLE tt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+CREATE TABLE tt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+CREATE TABLE tt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+INSERT INTO nt_1(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO nt_2(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO nt_3(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO nt_4(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO nt_5(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO nt_6(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_1(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_2(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_3(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_4(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_5(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_6(trans_id, stmt_id) VALUES(1,1);
+CREATE PROCEDURE pc_i_tt_5_suc (IN p_trans_id INTEGER, IN p_stmt_id INTEGER)
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM tt_5 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1);
+END|
+CREATE PROCEDURE pc_i_nt_5_suc (IN p_trans_id INTEGER, IN p_stmt_id INTEGER)
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM nt_5 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1);
+END|
+CREATE FUNCTION fc_i_tt_5_suc (p_trans_id INTEGER, p_stmt_id INTEGER) RETURNS VARCHAR(64)
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM tt_5 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1);
+RETURN "fc_i_tt_5_suc";
+END|
+CREATE FUNCTION fc_i_nt_5_suc (p_trans_id INTEGER, p_stmt_id INTEGER) RETURNS VARCHAR(64)
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM nt_5 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1);
+RETURN "fc_i_nt_5_suc";
+END|
+CREATE FUNCTION fc_i_nt_3_tt_3_suc (p_trans_id INTEGER, p_stmt_id INTEGER) RETURNS VARCHAR(64)
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM nt_3 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO nt_3(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+SELECT max(stmt_id) INTO in_stmt_id FROM tt_3 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO tt_3(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+RETURN "fc_i_nt_3_tt_3_suc";
+END|
+CREATE TRIGGER tr_i_tt_3_to_nt_3 AFTER INSERT ON tt_3 FOR EACH ROW
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM nt_3 WHERE trans_id= NEW.trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id;
+INSERT INTO nt_3(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id);
+INSERT INTO nt_3(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1);
+END|
+CREATE TRIGGER tr_i_nt_4_to_tt_4 AFTER INSERT ON nt_4 FOR EACH ROW
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM tt_4 WHERE trans_id= NEW.trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id;
+INSERT INTO tt_4(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id);
+INSERT INTO tt_4(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1);
+END|
+CREATE TRIGGER tr_i_tt_5_to_tt_6 AFTER INSERT ON tt_5 FOR EACH ROW
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM tt_6 WHERE trans_id= NEW.trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id, 1), 1) INTO in_stmt_id;
+INSERT INTO tt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id);
+INSERT INTO tt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1);
+END|
+CREATE TRIGGER tr_i_nt_5_to_nt_6 AFTER INSERT ON nt_5 FOR EACH ROW
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM nt_6 WHERE trans_id= NEW.trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id;
+INSERT INTO nt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id);
+INSERT INTO nt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1);
+END|
+###################################################################################
+# EXECUTE CASES CRASHING THE XID
+###################################################################################
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=T]
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (7, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-trig]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (8, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-func]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (9, 1);
+fc_i_tt_5_suc (9, 1)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-proc]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (10, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-trig C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (11, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (11, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-trig C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-trig C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-func C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (12, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (12, 4);
+fc_i_tt_5_suc (12, 4)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-func C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-func C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-proc C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (13, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (13, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-proc C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-proc C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-trig T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (14, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (14, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-func T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (15, 2);
+fc_i_tt_5_suc (15, 2)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (15, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-func T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-func T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-proc T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (16, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (16, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=T]
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (17, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-trig]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (18, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-func]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (19, 1);
+fc_i_tt_5_suc (19, 1)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-proc]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (20, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-trig C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (21, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (21, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-trig C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-trig C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-func C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (22, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (22, 4);
+fc_i_tt_5_suc (22, 4)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-func C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-func C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-proc C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (23, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (23, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-proc C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-proc C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-trig T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (24, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (24, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-func T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (25, 2);
+fc_i_tt_5_suc (25, 2)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (25, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-func T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-func T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-proc T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (26, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (26, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=T]
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (27, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-trig]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (28, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-func]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (29, 1);
+fc_i_tt_5_suc (29, 1)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-proc]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (30, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-trig C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (31, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (31, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-trig C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-trig C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-func C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (32, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (32, 4);
+fc_i_tt_5_suc (32, 4)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-func C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-func C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-proc C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (33, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (33, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-proc C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-proc C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-trig T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (34, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (34, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-func T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (35, 2);
+fc_i_tt_5_suc (35, 2)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (35, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-func T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-func T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-proc T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (36, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (36, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=T]
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (37, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-trig]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (38, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-func]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (39, 1);
+fc_i_tt_5_suc (39, 1)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-proc]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (40, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-trig C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (41, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (41, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-trig C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-trig C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-func C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (42, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (42, 4);
+fc_i_tt_5_suc (42, 4)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-func C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-func C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-proc C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (43, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (43, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-proc C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-proc C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-trig T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (44, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (44, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-func T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (45, 2);
+fc_i_tt_5_suc (45, 2)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (45, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-func T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-func T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-proc T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (46, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (46, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_5)
+master-bin.000001 # Table_map # # table_id: # (test.tt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Table_map # # table_id: # (test.tt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+###################################################################################
+# EXECUTE CASES CRASHING THE BEGIN/COMMIT
+###################################################################################
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_and_update_pos";;
+FAILURE d,crash_after_commit_and_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=N]
+-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO nt_1(trans_id, stmt_id) VALUES (47, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.nt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.nt_1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_and_update_pos";;
+FAILURE d,crash_after_commit_and_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=N-trig]
+-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO nt_5(trans_id, stmt_id) VALUES (48, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.nt_5)
+master-bin.000001 # Table_map # # table_id: # (test.nt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.nt_5)
+master-bin.000001 # Table_map # # table_id: # (test.nt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_and_update_pos";;
+FAILURE d,crash_after_commit_and_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=N-func]
+-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_nt_5_suc (49, 1);
+fc_i_nt_5_suc (49, 1)
+fc_i_nt_5_suc
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.nt_5)
+master-bin.000001 # Table_map # # table_id: # (test.nt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.nt_5)
+master-bin.000001 # Table_map # # table_id: # (test.nt_6)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+###################################################################################
+# CHECK CONSISTENCY
+###################################################################################
+include/sync_slave_sql_with_master.inc
+###################################################################################
+# CLEAN
+###################################################################################
+rpl_mixing_engines.inc [commands=clean]
+DROP TABLE tt_1;
+DROP TABLE tt_2;
+DROP TABLE tt_3;
+DROP TABLE tt_4;
+DROP TABLE tt_5;
+DROP TABLE tt_6;
+DROP TABLE nt_1;
+DROP TABLE nt_2;
+DROP TABLE nt_3;
+DROP TABLE nt_4;
+DROP TABLE nt_5;
+DROP TABLE nt_6;
+DROP PROCEDURE pc_i_tt_5_suc;
+DROP PROCEDURE pc_i_nt_5_suc;
+DROP FUNCTION fc_i_tt_5_suc;
+DROP FUNCTION fc_i_nt_5_suc;
+DROP FUNCTION fc_i_nt_3_tt_3_suc;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_blobs.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_blobs.result
new file mode 100644
index 00000000000..a0713d01593
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_blobs.result
@@ -0,0 +1,4739 @@
+include/rpl_init.inc [topology=1->2->3]
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+CON: 'server_1', IMG: 'NOBLOB', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'NOBLOB';
+SET GLOBAL binlog_row_image= 'NOBLOB';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image NOBLOB
+CON: 'server_2', IMG: 'NOBLOB', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'NOBLOB';
+SET GLOBAL binlog_row_image= 'NOBLOB';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image NOBLOB
+CON: 'server_3', IMG: 'NOBLOB', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'NOBLOB';
+SET GLOBAL binlog_row_image= 'NOBLOB';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image NOBLOB
+### engines: TokuDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+CON: 'server_1', IMG: 'MINIMAL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+CON: 'server_2', IMG: 'MINIMAL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+CON: 'server_3', IMG: 'MINIMAL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+### engines: TokuDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+CON: 'server_1', IMG: 'FULL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_2', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_3', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+### engines: TokuDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check when there is no key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the AI (they are not updated)
+### will not break replication (check even if there is a key in the table)
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (UK NOT NULL exists in the table)
+### will not break replication
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that updates without blobs in the BI (PK exists int the table)
+### will not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob in a key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a unique (not null) key does not break replication
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Asserts that declaring a blob as part of a primary key does not break replication
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_full.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_full.result
new file mode 100644
index 00000000000..d86105a3440
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_full.result
@@ -0,0 +1,3681 @@
+include/rpl_init.inc [topology=1->2->3]
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+CON: 'server_1', IMG: 'FULL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_2', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_3', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+### engines: TokuDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### Testing with TokuDB storage engine
+CON: 'server_1', IMG: 'MINIMAL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+CON: 'server_2', IMG: 'MINIMAL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+CON: 'server_3', IMG: 'MINIMAL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+#### case #1: AI: no values logged
+CREATE TABLE t1 (c1 int DEFAULT 100) Engine=ENGINE;
+INSERT INTO t1 VALUES ();
+SELECT * FROM t1;
+c1
+100
+include/rpl_sync.inc
+SELECT * FROM t1;
+c1
+100
+SELECT * FROM t1;
+c1
+100
+DROP TABLE t1;
+include/rpl_sync.inc
+#### case #2: AI: not empty but slave does not have usable data for its columns (INSERT)
+CREATE TABLE t1 (c1 int DEFAULT 100) Engine=ENGINE;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100) Engine=ENGINE;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100, c2 int, primary key(c2)) Engine=ENGINE;
+SET SQL_LOG_BIN=1;
+INSERT INTO t1(c2) VALUES (1);
+SELECT * FROM t1;
+c1 c2
+100 1
+include/rpl_sync.inc
+SELECT * FROM t1;
+c1
+100
+SELECT * FROM t1;
+c1
+100
+DROP TABLE t1;
+include/rpl_sync.inc
+#### case #3: BI: usable columns on the slave, AI: no usable columns on the slave
+CREATE TABLE t1 (c1 int DEFAULT 100) Engine=ENGINE;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100) Engine=ENGINE;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100, c2 int) Engine=ENGINE;
+SET SQL_LOG_BIN=1;
+INSERT INTO t1 VALUES (1,1);
+SELECT * FROM t1;
+c1 c2
+1 1
+include/rpl_sync.inc
+SELECT * FROM t1;
+c1
+1
+SELECT * FROM t1;
+c1
+1
+UPDATE t1 SET c2=2 WHERE c1=1 AND c2=1;
+SELECT * FROM t1;
+c1 c2
+1 2
+include/rpl_sync.inc
+SELECT * FROM t1;
+c1
+1
+SELECT * FROM t1;
+c1
+1
+DROP TABLE t1;
+include/rpl_sync.inc
+#### case #4: AI, BI: no usable columns on the slave (NOOP UPDATE).
+####
+CREATE TABLE t1 (c1 int DEFAULT 100) Engine=ENGINE;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100) Engine=ENGINE;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100, c2 int, c3 int, primary key(c2)) Engine=ENGINE;
+SET SQL_LOG_BIN=1;
+INSERT INTO t1 VALUES (1,1,1);
+SELECT * FROM t1;
+c1 c2 c3
+1 1 1
+include/rpl_sync.inc
+SELECT * FROM t1;
+c1
+1
+SELECT * FROM t1;
+c1
+1
+UPDATE t1 SET c3=300 WHERE c2=1;
+SELECT * FROM t1;
+c1 c2 c3
+1 1 300
+include/rpl_sync.inc
+SELECT * FROM t1;
+c1
+1
+SELECT * FROM t1;
+c1
+1
+DROP TABLE t1;
+include/rpl_sync.inc
+#### case #5: BI: no usable columns on the slave, AI: usable columns on the slave (slave must stop).
+####
+CREATE TABLE t1 (c1 INT DEFAULT 100) Engine=ENGINE;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 INT DEFAULT 100) Engine=ENGINE;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 INT DEFAULT 100, c2 INT PRIMARY KEY) Engine=ENGINE;
+SET SQL_LOG_BIN=1;
+INSERT INTO t1 VALUES (1,1);
+SELECT * FROM t1;
+c1 c2
+1 1
+include/rpl_sync.inc
+SELECT * FROM t1;
+c1
+1
+SELECT * FROM t1;
+c1
+1
+UPDATE t1 SET c1=300 WHERE c2=1;
+SELECT * FROM t1;
+c1 c2
+300 1
+SET SQL_LOG_BIN=0;
+call mtr.add_suppression("Slave: Can\'t find record in \'t1\' Error_code: 1032");
+call mtr.add_suppression("Slave SQL: .*Could not execute Update_rows event on table test.t1; Can.t find record in .t1.* Error_code: 1032");
+call mtr.add_suppression("The slave coordinator and worker threads are stopped, possibly leaving data in inconsistent state");
+SET SQL_LOG_BIN=1;
+include/wait_for_slave_sql_error_and_skip.inc [errno=1032]
+DROP TABLE t1;
+include/rpl_sync.inc
+CON: 'server_1', IMG: 'FULL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_2', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_3', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_min.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_min.result
new file mode 100644
index 00000000000..45a5e6ee341
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_min.result
@@ -0,0 +1,3522 @@
+include/rpl_init.inc [topology=1->2->3]
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+CON: 'server_1', IMG: 'MINIMAL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+CON: 'server_2', IMG: 'MINIMAL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+CON: 'server_3', IMG: 'MINIMAL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+### engines: TokuDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+CON: 'server_1', IMG: 'FULL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_2', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_3', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_noblob.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_noblob.result
new file mode 100644
index 00000000000..52906a7ee36
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_noblob.result
@@ -0,0 +1,3522 @@
+include/rpl_init.inc [topology=1->2->3]
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+CON: 'server_1', IMG: 'NOBLOB', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'NOBLOB';
+SET GLOBAL binlog_row_image= 'NOBLOB';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image NOBLOB
+CON: 'server_2', IMG: 'NOBLOB', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'NOBLOB';
+SET GLOBAL binlog_row_image= 'NOBLOB';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image NOBLOB
+CON: 'server_3', IMG: 'NOBLOB', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'NOBLOB';
+SET GLOBAL binlog_row_image= 'NOBLOB';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image NOBLOB
+### engines: TokuDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, TokuDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, InnoDB
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes in master, but NULLABLE on first slave
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite NOT NULL Unique key with holes
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int NOT NULL, c2 char(1), c3 char(1) NOT NULL, c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key with holes
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c3)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Primary Key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Primary key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Unique key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), unique key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+****** TEST: One Composite key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1,c2)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: One key
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1), key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+******* TEST: No keys
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 char(1), c3 char(1), c4 char(1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, '1', '1', '1' );
+INSERT INTO t VALUES (4, '4', '4', '4' );
+INSERT INTO t VALUES (7, '7', '7', '7' );
+INSERT INTO t VALUES (9, '9', '9', NULL );
+INSERT INTO t VALUES (2, '1', '2', '2' );
+INSERT INTO t VALUES (3, '1', '3', '2' );
+include/rpl_sync.inc
+UPDATE t SET c4 = '7';
+UPDATE t SET c4 = '5' WHERE c1 = 1;
+UPDATE t SET c2 = '5' WHERE c1 = 1;
+UPDATE t SET c1 = '5' WHERE c1 = 1;
+UPDATE t SET c4 = '8' WHERE c2 = '4';
+UPDATE t SET c1 = '8' WHERE c2 = '4';
+UPDATE t SET c2 = '8' WHERE c2 = '4';
+UPDATE t SET c3 = '0' WHERE c4 = NULL;
+UPDATE t SET c2 = '0' WHERE c4 = '0';
+UPDATE t SET c2 = '2' WHERE c4 = '2';
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c1 = 7;
+DELETE FROM t WHERE c1 = 8;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+CON: 'server_1', IMG: 'FULL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_2', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_3', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_full.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_full.result
new file mode 100644
index 00000000000..e802156918e
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_full.result
@@ -0,0 +1,3505 @@
+include/rpl_init.inc [topology=1->2->3]
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+CON: 'server_1', IMG: 'FULL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_2', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_3', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+### engines: TokuDB, TokuDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, TokuDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_min.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_min.result
new file mode 100644
index 00000000000..368b3b5f938
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_min.result
@@ -0,0 +1,3530 @@
+include/rpl_init.inc [topology=1->2->3]
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+CON: 'server_1', IMG: 'MINIMAL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+CON: 'server_2', IMG: 'MINIMAL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+CON: 'server_3', IMG: 'MINIMAL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image MINIMAL
+### engines: TokuDB, TokuDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, TokuDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+CON: 'server_1', IMG: 'FULL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_2', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_3', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_noblob.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_noblob.result
new file mode 100644
index 00000000000..bb6c3ea1c3e
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_noblob.result
@@ -0,0 +1,3530 @@
+include/rpl_init.inc [topology=1->2->3]
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+CON: 'server_1', IMG: 'NOBLOB', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'NOBLOB';
+SET GLOBAL binlog_row_image= 'NOBLOB';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image NOBLOB
+CON: 'server_2', IMG: 'NOBLOB', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'NOBLOB';
+SET GLOBAL binlog_row_image= 'NOBLOB';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image NOBLOB
+CON: 'server_3', IMG: 'NOBLOB', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'NOBLOB';
+SET GLOBAL binlog_row_image= 'NOBLOB';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image NOBLOB
+### engines: TokuDB, TokuDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, TokuDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: TokuDB, InnoDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, TokuDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= TokuDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, TokuDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= TokuDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+### engines: InnoDB, InnoDB, InnoDB
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no keys slaves with no keys as well
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with keys
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields (first slave with UK NOT NULL, second with PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with no key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, first slave with key on different field and second slave with key on yet another different field.
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields (first slave has UK NOT NULL)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with Key, slaves with PKs on different fields
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, slaves with no keys
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NULLABLE, first slave with K on different field second slave with key on yet another different field
+CREATE TABLE t (c1 int, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL, first slave with UK NOT NULL on different field
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with UK NOT NULL and slaves with PK on different fields
+CREATE TABLE t (c1 int NOT NULL, c2 blob, c3 int, unique key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and no keys on the slaves
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Master with PK and first slave with KEY only
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c3)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, key(c2(512))) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave (which has unique NOT NULL key instead of PK)
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, unique key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob NOT NULL, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+SET SQL_LOG_BIN=0;
+### Different PKs on master and first slave
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c2(512))) engine= InnoDB;;
+CREATE TABLE t (c1 int, c2 blob, c3 int, primary key(c1)) engine= InnoDB;;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=1;
+INSERT INTO t VALUES (1, "a", 10);
+INSERT INTO t VALUES (2, "b", 20);
+INSERT INTO t VALUES (3, "c", 30);
+include/rpl_sync.inc
+UPDATE t SET c1=10 WHERE c2="a";
+UPDATE t SET c1=20 WHERE c1=2;
+UPDATE t SET c1=30 WHERE c3=30;
+UPDATE t SET c3=40 WHERE c1=30;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DELETE FROM t WHERE c2="a";
+DELETE FROM t WHERE c1=20;
+DELETE FROM t;
+include/rpl_sync.inc
+include/diff_tables.inc [server_1:test.t, server_2:test.t, server_3:test.t]
+DROP TABLE t;
+include/rpl_sync.inc
+CON: 'server_1', IMG: 'FULL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_2', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+CON: 'server_3', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name Value
+binlog_row_image FULL
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_log.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_log.result
new file mode 100644
index 00000000000..87ffbca71bc
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_log.result
@@ -0,0 +1,275 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+include/sync_slave_sql_with_master.inc
+include/stop_slave.inc
+include/wait_for_slave_to_stop.inc
+reset master;
+reset slave;
+start slave;
+include/wait_for_slave_to_start.inc
+create table t1(n int not null auto_increment primary key)ENGINE=TokuDB;
+insert into t1 values (NULL);
+drop table t1;
+create table t1 (word char(20) not null)ENGINE=TokuDB;
+load data infile 'LOAD_FILE' into table t1 ignore 1 lines;
+select count(*) from t1;
+count(*)
+69
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=TokuDB
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
+master-bin.000001 # Query # # use `test`; create table t1 (word char(20) not null)ENGINE=TokuDB
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=TokuDB
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+flush logs;
+create table t3 (a int)ENGINE=TokuDB;
+select * from t1 order by 1 asc;
+word
+Aarhus
+Aaron
+Aaron
+Ababa
+Ababa
+aback
+aback
+abaft
+abaft
+abandon
+abandon
+abandoned
+abandoned
+abandoning
+abandoning
+abandonment
+abandonment
+abandons
+abandons
+abase
+abased
+abasement
+abasements
+abases
+abash
+abashed
+abashes
+abashing
+abasing
+abate
+abated
+abatement
+abatements
+abater
+abates
+abating
+Abba
+abbe
+abbey
+abbeys
+abbot
+abbots
+Abbott
+abbreviate
+abbreviated
+abbreviates
+abbreviating
+abbreviation
+abbreviations
+Abby
+abdomen
+abdomens
+abdominal
+abduct
+abducted
+abduction
+abductions
+abductor
+abductors
+abducts
+Abe
+abed
+Abel
+Abelian
+Abelson
+Aberdeen
+Abernathy
+aberrant
+aberration
+include/sync_slave_sql_with_master.inc
+select * from t1 order by 1 asc;
+word
+Aarhus
+Aaron
+Aaron
+Ababa
+Ababa
+aback
+aback
+abaft
+abaft
+abandon
+abandon
+abandoned
+abandoned
+abandoning
+abandoning
+abandonment
+abandonment
+abandons
+abandons
+abase
+abased
+abasement
+abasements
+abases
+abash
+abashed
+abashes
+abashing
+abasing
+abate
+abated
+abatement
+abatements
+abater
+abates
+abating
+Abba
+abbe
+abbey
+abbeys
+abbot
+abbots
+Abbott
+abbreviate
+abbreviated
+abbreviates
+abbreviating
+abbreviation
+abbreviations
+Abby
+abdomen
+abdomens
+abdominal
+abduct
+abducted
+abduction
+abductions
+abductor
+abductors
+abducts
+Abe
+abed
+Abel
+Abelian
+Abelson
+Aberdeen
+Abernathy
+aberrant
+aberration
+flush logs;
+include/stop_slave.inc
+include/start_slave.inc
+create table t2 (n int)ENGINE=TokuDB;
+insert into t2 values (1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=TokuDB
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
+master-bin.000001 # Query # # use `test`; create table t1 (word char(20) not null)ENGINE=TokuDB
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Rotate # # master-bin.000002;pos=POS
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB
+master-bin.000002 # Query # # use `test`; create table t2 (n int)ENGINE=TokuDB
+master-bin.000002 # Query # # BEGIN
+master-bin.000002 # Table_map # # table_id: # (test.t2)
+master-bin.000002 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000002 # Xid # # COMMIT /* XID */
+show binary logs;
+Log_name File_size
+master-bin.000001 #
+master-bin.000002 #
+include/sync_slave_sql_with_master.inc
+show binary logs;
+Log_name File_size
+slave-bin.000001 #
+slave-bin.000002 #
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000001 # Query # # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=TokuDB
+slave-bin.000001 # Query # # BEGIN
+slave-bin.000001 # Table_map # # table_id: # (test.t1)
+slave-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+slave-bin.000001 # Xid # # COMMIT /* XID */
+slave-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
+slave-bin.000001 # Query # # use `test`; create table t1 (word char(20) not null)ENGINE=TokuDB
+slave-bin.000001 # Query # # BEGIN
+slave-bin.000001 # Table_map # # table_id: # (test.t1)
+slave-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+slave-bin.000001 # Xid # # COMMIT /* XID */
+slave-bin.000001 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB
+slave-bin.000001 # Rotate # # slave-bin.000002;pos=POS
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000002 # Query # # use `test`; create table t2 (n int)ENGINE=TokuDB
+slave-bin.000002 # Query # # BEGIN
+slave-bin.000002 # Table_map # # table_id: # (test.t2)
+slave-bin.000002 # Write_rows # # table_id: # flags: STMT_END_F
+slave-bin.000002 # Xid # # COMMIT /* XID */
+include/check_slave_is_running.inc
+show binlog events in 'slave-bin.000005' from 4;
+ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+include/rpl_reset.inc
+create table t1(a int auto_increment primary key, b int);
+insert into t1 values (NULL, 1);
+set insert_id=5;
+insert into t1 values (NULL, last_insert_id()), (NULL, last_insert_id());
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; create table t1(a int auto_increment primary key, b int)
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+select * from t1;
+a b
+1 1
+5 1
+6 1
+drop table t1;
+include/sync_slave_sql_with_master.inc
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_lower_case_table_names.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_lower_case_table_names.result
new file mode 100644
index 00000000000..d4a50261d60
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_lower_case_table_names.result
@@ -0,0 +1,51 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+******** [ MASTER ] ********
+CREATE DATABASE BUG_37656;
+use BUG_37656;
+show databases like 'BUG_37656';
+Database (BUG_37656)
+BUG_37656
+******** [ SLAVE ] ********
+show databases like 'bug_37656';
+Database (bug_37656)
+bug_37656
+******** [ MASTER ] ********
+CREATE TABLE T1 (a int);
+CREATE TABLE T2 (b int) ENGINE=TokuDB;
+CREATE TABLE T3 (txt TEXT);
+show tables;
+Tables_in_BUG_37656
+T1
+T2
+T3
+******** [ SLAVE ] ********
+use bug_37656;
+show tables;
+Tables_in_bug_37656
+t2
+t3
+CREATE TABLE t1 (a INT);
+******** [ MASTER ] ********
+use BUG_37656;
+INSERT INTO T1 VALUES (1);
+INSERT INTO T2 VALUES (1);
+use test;
+INSERT INTO BUG_37656.T1 VALUES (2);
+INSERT INTO BUG_37656.T2 VALUES (2);
+LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE BUG_37656.T3;
+******** [ SLAVE ] ********
+include/diff_tables.inc [master:BUG_37656.T2, slave:bug_37656.t2]
+include/diff_tables.inc [master:BUG_37656.T3, slave:bug_37656.t3]
+******** [ MASTER ] ********
+DROP DATABASE BUG_37656;
+include/rpl_reset.inc
+CREATE DATABASE B50653;
+USE B50653;
+CREATE PROCEDURE b50653_proc() BEGIN SELECT 1; END;
+DROP PROCEDURE b50653_proc;
+DROP DATABASE B50653;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp003.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp003.result
new file mode 100644
index 00000000000..dc3a8a55741
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp003.result
@@ -0,0 +1,60 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP TABLE IF EXISTS test.t1;
+CREATE TABLE test.t1(a INT,PRIMARY KEY(a))ENGINE=TOKUDB;
+CREATE PROCEDURE test.p1()
+BEGIN
+INSERT INTO test.t1 VALUES (4);
+SELECT get_lock("test", 100);
+UPDATE test.t1 set a=a+4 WHERE a=4;
+END|
+CREATE PROCEDURE test.p2()
+BEGIN
+UPDATE test.t1 SET a=a+1;
+END|
+SELECT get_lock("test", 200);
+get_lock("test", 200)
+1
+CALL test.p1();
+CALL test.p2();
+SELECT release_lock("test");
+release_lock("test")
+1
+get_lock("test", 100)
+1
+SELECT release_lock("test");
+release_lock("test")
+1
+SELECT * FROM test.t1;
+a
+5
+include/sync_slave_sql_with_master.inc
+SELECT * FROM test.t1;
+a
+5
+DROP TABLE IF EXISTS test.t1;
+CREATE TABLE test.t1(a INT,PRIMARY KEY(a))ENGINE=TOKUDB;
+CALL test.p2();
+CALL test.p1();
+get_lock("test", 100)
+1
+SELECT release_lock("test");
+release_lock("test")
+1
+SELECT * FROM test.t1;
+a
+8
+include/sync_slave_sql_with_master.inc
+SELECT * FROM test.t1;
+a
+8
+DROP PROCEDURE IF EXISTS test.p1;
+DROP PROCEDURE IF EXISTS test.p2;
+DROP TABLE IF EXISTS test.t1;
+include/sync_slave_sql_with_master.inc
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp006.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp006.result
new file mode 100644
index 00000000000..b6fc475eeef
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp006.result
@@ -0,0 +1,47 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+CREATE TABLE IF NOT EXISTS t1(name CHAR(16), birth DATE,PRIMARY KEY(name))ENGINE=TokuDB;
+CREATE TABLE IF NOT EXISTS t2(name CHAR(16), age INT ,PRIMARY KEY(name))ENGINE=TokuDB;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE spa CHAR(16);
+DECLARE spb INT;
+DECLARE cur1 CURSOR FOR SELECT name,
+(YEAR(CURDATE())-YEAR(birth))-(RIGHT(CURDATE(),5)--.' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' IGNORE 1 LINES (`word`) ;file_id=#
+slave-bin.000001 # Xid # # COMMIT /* XID */
+slave-bin.000001 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB
+slave-bin.000001 # Rotate # # slave-bin.000002;pos=POS
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000002 # Query # # use `test`; create table t2 (n int)ENGINE=TokuDB
+slave-bin.000002 # Query # # BEGIN
+slave-bin.000002 # Query # # use `test`; insert into t2 values (1)
+slave-bin.000002 # Xid # # COMMIT /* XID */
+include/check_slave_is_running.inc
+show binlog events in 'slave-bin.000005' from 4;
+ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+include/rpl_reset.inc
+create table t1(a int auto_increment primary key, b int);
+insert into t1 values (NULL, 1);
+set insert_id=5;
+insert into t1 values (NULL, last_insert_id()), (NULL, last_insert_id());
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; create table t1(a int auto_increment primary key, b int)
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Intvar # # INSERT_ID=1
+master-bin.000001 # Query # # use `test`; insert into t1 values (NULL, 1)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Intvar # # LAST_INSERT_ID=1
+master-bin.000001 # Intvar # # INSERT_ID=5
+master-bin.000001 # Query # # use `test`; insert into t1 values (NULL, last_insert_id()), (NULL, last_insert_id())
+master-bin.000001 # Query # # COMMIT
+select * from t1;
+a b
+1 1
+5 1
+6 1
+drop table t1;
+include/sync_slave_sql_with_master.inc
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_crash_safe.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_crash_safe.result
new file mode 100644
index 00000000000..226a2b93140
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_crash_safe.result
@@ -0,0 +1,1773 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+call mtr.add_suppression('Attempting backtrace');
+call mtr.add_suppression("Recovery from master pos .* and file master-bin.000001");
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+call mtr.add_suppression(".* InnoDB: Warning: allocated tablespace .*, old maximum was .*");
+###################################################################################
+# PREPARE EXECUTION
+###################################################################################
+include/stop_slave.inc
+SHOW CREATE TABLE mysql.slave_relay_log_info;
+Table Create Table
+slave_relay_log_info CREATE TABLE `slave_relay_log_info` (
+ `Number_of_lines` int(10) unsigned NOT NULL COMMENT 'Number of lines in the file or rows in the table. Used to version table definitions.',
+ `Relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'The name of the current relay log file.',
+ `Relay_log_pos` bigint(20) unsigned NOT NULL COMMENT 'The relay log position of the last executed event.',
+ `Master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'The name of the master binary log file from which the events in the relay log file were read.',
+ `Master_log_pos` bigint(20) unsigned NOT NULL COMMENT 'The master log position of the last executed event.',
+ `Sql_delay` int(11) NOT NULL COMMENT 'The number of seconds that the slave must lag behind the master.',
+ `Number_of_workers` int(10) unsigned NOT NULL,
+ `Id` int(10) unsigned NOT NULL COMMENT 'Internal Id that uniquely identifies this record.',
+ PRIMARY KEY (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT='Relay Log Information'
+SHOW CREATE TABLE mysql.slave_worker_info;
+Table Create Table
+slave_worker_info CREATE TABLE `slave_worker_info` (
+ `Id` int(10) unsigned NOT NULL,
+ `Relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Relay_log_pos` bigint(20) unsigned NOT NULL,
+ `Master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Master_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Checkpoint_relay_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Checkpoint_master_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_seqno` int(10) unsigned NOT NULL,
+ `Checkpoint_group_size` int(10) unsigned NOT NULL,
+ `Checkpoint_group_bitmap` blob NOT NULL,
+ PRIMARY KEY (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT='Worker Information'
+ALTER TABLE mysql.slave_relay_log_info ENGINE= Innodb;
+ALTER TABLE mysql.slave_worker_info ENGINE= Innodb;
+SHOW CREATE TABLE mysql.slave_relay_log_info;
+Table Create Table
+slave_relay_log_info CREATE TABLE `slave_relay_log_info` (
+ `Number_of_lines` int(10) unsigned NOT NULL COMMENT 'Number of lines in the file or rows in the table. Used to version table definitions.',
+ `Relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'The name of the current relay log file.',
+ `Relay_log_pos` bigint(20) unsigned NOT NULL COMMENT 'The relay log position of the last executed event.',
+ `Master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'The name of the master binary log file from which the events in the relay log file were read.',
+ `Master_log_pos` bigint(20) unsigned NOT NULL COMMENT 'The master log position of the last executed event.',
+ `Sql_delay` int(11) NOT NULL COMMENT 'The number of seconds that the slave must lag behind the master.',
+ `Number_of_workers` int(10) unsigned NOT NULL,
+ `Id` int(10) unsigned NOT NULL COMMENT 'Internal Id that uniquely identifies this record.',
+ PRIMARY KEY (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT='Relay Log Information'
+SHOW CREATE TABLE mysql.slave_worker_info;
+Table Create Table
+slave_worker_info CREATE TABLE `slave_worker_info` (
+ `Id` int(10) unsigned NOT NULL,
+ `Relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Relay_log_pos` bigint(20) unsigned NOT NULL,
+ `Master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Master_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Checkpoint_relay_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `Checkpoint_master_log_pos` bigint(20) unsigned NOT NULL,
+ `Checkpoint_seqno` int(10) unsigned NOT NULL,
+ `Checkpoint_group_size` int(10) unsigned NOT NULL,
+ `Checkpoint_group_bitmap` blob NOT NULL,
+ PRIMARY KEY (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT='Worker Information'
+include/start_slave.inc
+rpl_mixing_engines.inc [commands=configure]
+CREATE TABLE nt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE nt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE nt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE nt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE nt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE nt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM;
+CREATE TABLE tt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+CREATE TABLE tt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+CREATE TABLE tt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+CREATE TABLE tt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+CREATE TABLE tt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+CREATE TABLE tt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = TokuDB;
+INSERT INTO nt_1(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO nt_2(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO nt_3(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO nt_4(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO nt_5(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO nt_6(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_1(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_2(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_3(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_4(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_5(trans_id, stmt_id) VALUES(1,1);
+INSERT INTO tt_6(trans_id, stmt_id) VALUES(1,1);
+CREATE PROCEDURE pc_i_tt_5_suc (IN p_trans_id INTEGER, IN p_stmt_id INTEGER)
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM tt_5 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1);
+END|
+CREATE PROCEDURE pc_i_nt_5_suc (IN p_trans_id INTEGER, IN p_stmt_id INTEGER)
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM nt_5 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1);
+END|
+CREATE FUNCTION fc_i_tt_5_suc (p_trans_id INTEGER, p_stmt_id INTEGER) RETURNS VARCHAR(64)
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM tt_5 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1);
+RETURN "fc_i_tt_5_suc";
+END|
+CREATE FUNCTION fc_i_nt_5_suc (p_trans_id INTEGER, p_stmt_id INTEGER) RETURNS VARCHAR(64)
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM nt_5 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1);
+RETURN "fc_i_nt_5_suc";
+END|
+CREATE FUNCTION fc_i_nt_3_tt_3_suc (p_trans_id INTEGER, p_stmt_id INTEGER) RETURNS VARCHAR(64)
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM nt_3 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO nt_3(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+SELECT max(stmt_id) INTO in_stmt_id FROM tt_3 WHERE trans_id= p_trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id;
+INSERT INTO tt_3(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id);
+RETURN "fc_i_nt_3_tt_3_suc";
+END|
+CREATE TRIGGER tr_i_tt_3_to_nt_3 AFTER INSERT ON tt_3 FOR EACH ROW
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM nt_3 WHERE trans_id= NEW.trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id;
+INSERT INTO nt_3(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id);
+INSERT INTO nt_3(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1);
+END|
+CREATE TRIGGER tr_i_nt_4_to_tt_4 AFTER INSERT ON nt_4 FOR EACH ROW
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM tt_4 WHERE trans_id= NEW.trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id;
+INSERT INTO tt_4(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id);
+INSERT INTO tt_4(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1);
+END|
+CREATE TRIGGER tr_i_tt_5_to_tt_6 AFTER INSERT ON tt_5 FOR EACH ROW
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM tt_6 WHERE trans_id= NEW.trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id, 1), 1) INTO in_stmt_id;
+INSERT INTO tt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id);
+INSERT INTO tt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1);
+END|
+CREATE TRIGGER tr_i_nt_5_to_nt_6 AFTER INSERT ON nt_5 FOR EACH ROW
+BEGIN
+DECLARE in_stmt_id INTEGER;
+SELECT max(stmt_id) INTO in_stmt_id FROM nt_6 WHERE trans_id= NEW.trans_id;
+SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id;
+INSERT INTO nt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id);
+INSERT INTO nt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1);
+END|
+###################################################################################
+# EXECUTE CASES CRASHING THE XID
+###################################################################################
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=T]
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (7, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (7, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (7, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-trig]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (8, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (8, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (8, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-func]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (9, 1);
+fc_i_tt_5_suc (9, 1)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(9,1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(9,1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-proc]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (10, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',10), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',10), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',10), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',10), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-trig C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (11, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (11, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (11, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (11, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-trig C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (11, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (11, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-trig C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-func C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (12, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (12, 4);
+fc_i_tt_5_suc (12, 4)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (12, 2)
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(12,4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-func C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (12, 2)
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(12,4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-func C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-proc C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (13, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (13, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (13, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',13), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',13), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-proc C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (13, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',13), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',13), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-proc C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-trig T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (14, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (14, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (14, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (14, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (14, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (14, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-func T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (15, 2);
+fc_i_tt_5_suc (15, 2)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (15, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(15,2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (15, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-func T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(15,2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (15, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-func T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_apply";;
+FAILURE d,crash_after_apply and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-proc T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (16, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (16, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',16), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',16), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (16, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',16), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',16), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (16, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=T]
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (17, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (17, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (17, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-trig]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (18, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (18, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (18, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-func]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (19, 1);
+fc_i_tt_5_suc (19, 1)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(19,1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(19,1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-proc]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (20, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',20), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',20), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',20), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',20), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-trig C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (21, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (21, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (21, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (21, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-trig C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (21, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (21, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-trig C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-func C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (22, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (22, 4);
+fc_i_tt_5_suc (22, 4)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (22, 2)
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(22,4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-func C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (22, 2)
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(22,4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-func C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-proc C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (23, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (23, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (23, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',23), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',23), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-proc C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (23, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',23), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',23), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-proc C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-trig T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (24, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (24, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (24, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (24, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (24, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (24, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-func T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (25, 2);
+fc_i_tt_5_suc (25, 2)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (25, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(25,2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (25, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-func T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(25,2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (25, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-func T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_before_update_pos";;
+FAILURE d,crash_before_update_pos and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-proc T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (26, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (26, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',26), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',26), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (26, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',26), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',26), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (26, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=T]
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (27, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (27, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (27, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-trig]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (28, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (28, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (28, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-func]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (29, 1);
+fc_i_tt_5_suc (29, 1)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(29,1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(29,1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=T-proc]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (30, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',30), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',30), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',30), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',30), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-trig C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (31, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (31, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (31, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (31, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-trig C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (31, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (31, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-trig C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-func C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (32, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (32, 4);
+fc_i_tt_5_suc (32, 4)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (32, 2)
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(32,4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-func C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (32, 2)
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(32,4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-func C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T T-proc C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (33, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (33, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (33, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',33), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',33), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-proc C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (33, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',33), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',33), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-proc C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-trig T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (34, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (34, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (34, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (34, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (34, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (34, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-func T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (35, 2);
+fc_i_tt_5_suc (35, 2)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (35, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(35,2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (35, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-func T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(35,2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (35, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-func T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_update_pos_before_apply";;
+FAILURE d,crash_after_update_pos_before_apply and OUTCOME O1
+rpl_mixing_engines.inc [commands=B T-proc T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (36, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (36, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',36), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',36), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (36, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',36), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',36), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (36, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=T]
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (37, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (37, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (37, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-trig]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (38, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (38, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (38, 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-func]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (39, 1);
+fc_i_tt_5_suc (39, 1)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(39,1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(39,1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=T-proc]
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (40, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',40), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',40), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',40), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',40), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-trig C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (41, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (41, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (41, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (41, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-trig C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (41, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (41, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-trig C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-func C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (42, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (42, 4);
+fc_i_tt_5_suc (42, 4)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (42, 2)
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(42,4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-func C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (42, 2)
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(42,4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-func C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T T-proc C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (43, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (43, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (43, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',43), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',43), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T T-proc C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (43, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',43), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',43), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T T-proc C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-trig T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_5(trans_id, stmt_id) VALUES (44, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (44, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (44, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (44, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (44, 2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (44, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-func T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_tt_5_suc (45, 2);
+fc_i_tt_5_suc (45, 2)
+fc_i_tt_5_suc
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (45, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(45,2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (45, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-func T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(45,2)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (45, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-func T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_before_update_pos";;
+FAILURE d,crash_after_commit_before_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=B T-proc T C]
+-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b-
+BEGIN;
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b-
+CALL pc_i_tt_5_suc (46, 2);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO tt_1(trans_id, stmt_id) VALUES (46, 4);
+include/show_binlog_events.inc
+-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b-
+COMMIT;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',46), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',46), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (46, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc T C << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',46), NAME_CONST('in_stmt_id',1))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',46), NAME_CONST('in_stmt_id',1) + 1)
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (46, 4)
+master-bin.000001 # Xid # # COMMIT /* XID */
+-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc T C << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+###################################################################################
+# EXECUTE CASES CRASHING THE BEGIN/COMMIT
+###################################################################################
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_and_update_pos";;
+FAILURE d,crash_after_commit_and_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=N]
+-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO nt_1(trans_id, stmt_id) VALUES (47, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (47, 1)
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (47, 1)
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_and_update_pos";;
+FAILURE d,crash_after_commit_and_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=N-trig]
+-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b-
+INSERT INTO nt_5(trans_id, stmt_id) VALUES (48, 1);
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (48, 1)
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (48, 1)
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+
+
+
+STOP SLAVE SQL_THREAD;
+include/wait_for_slave_sql_to_stop.inc
+SET GLOBAL debug="d,crash_after_commit_and_update_pos";;
+FAILURE d,crash_after_commit_and_update_pos and OUTCOME O2
+rpl_mixing_engines.inc [commands=N-func]
+-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b-
+SELECT fc_i_nt_5_suc (49, 1);
+fc_i_nt_5_suc (49, 1)
+fc_i_nt_5_suc
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(49,1)
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e-
+-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b-
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(49,1)
+master-bin.000001 # Query # # COMMIT
+-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e-
+
+include/rpl_reconnect.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
+###################################################################################
+# CHECK CONSISTENCY
+###################################################################################
+include/sync_slave_sql_with_master.inc
+###################################################################################
+# CLEAN
+###################################################################################
+rpl_mixing_engines.inc [commands=clean]
+DROP TABLE tt_1;
+DROP TABLE tt_2;
+DROP TABLE tt_3;
+DROP TABLE tt_4;
+DROP TABLE tt_5;
+DROP TABLE tt_6;
+DROP TABLE nt_1;
+DROP TABLE nt_2;
+DROP TABLE nt_3;
+DROP TABLE nt_4;
+DROP TABLE nt_5;
+DROP TABLE nt_6;
+DROP PROCEDURE pc_i_tt_5_suc;
+DROP PROCEDURE pc_i_nt_5_suc;
+DROP FUNCTION fc_i_tt_5_suc;
+DROP FUNCTION fc_i_nt_5_suc;
+DROP FUNCTION fc_i_nt_3_tt_3_suc;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_lower_case_table_names.result b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_lower_case_table_names.result
new file mode 100644
index 00000000000..e3d83733ed0
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_lower_case_table_names.result
@@ -0,0 +1,48 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+******** [ MASTER ] ********
+CREATE DATABASE BUG_37656;
+use BUG_37656;
+show databases like 'BUG_37656';
+Database (BUG_37656)
+BUG_37656
+******** [ SLAVE ] ********
+show databases like 'bug_37656';
+Database (bug_37656)
+bug_37656
+******** [ MASTER ] ********
+CREATE TABLE T1 (a int);
+CREATE TABLE T2 (b int) ENGINE=TokuDB;
+CREATE TABLE T3 (txt TEXT);
+show tables;
+Tables_in_BUG_37656
+T1
+T2
+T3
+******** [ SLAVE ] ********
+use bug_37656;
+show tables;
+Tables_in_bug_37656
+t2
+t3
+CREATE TABLE t1 (a INT);
+******** [ MASTER ] ********
+use BUG_37656;
+INSERT INTO T1 VALUES (1);
+INSERT INTO T2 VALUES (1);
+LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE BUG_37656.T3;
+******** [ SLAVE ] ********
+include/diff_tables.inc [master:BUG_37656.T2, slave:bug_37656.t2]
+include/diff_tables.inc [master:BUG_37656.T3, slave:bug_37656.t3]
+******** [ MASTER ] ********
+DROP DATABASE BUG_37656;
+include/rpl_reset.inc
+CREATE DATABASE B50653;
+USE B50653;
+CREATE PROCEDURE b50653_proc() BEGIN SELECT 1; END;
+DROP PROCEDURE b50653_proc;
+DROP DATABASE B50653;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_not_null_tokudb.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_not_null_tokudb.test
index 8fde1c3415b..53cf555ce64 100644
--- a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_not_null_tokudb.test
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_not_null_tokudb.test
@@ -11,10 +11,10 @@
# 3 - NULL --> NOT NULL ( sql-mode != STRICT and no failures)
#
#################################################################################
---source include/master-slave.inc
--source include/have_tokudb.inc
--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
-let $engine=Innodb;
+let $engine=TokuDB;
--source extra/rpl_tests/rpl_not_null.test
--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_basic_3tokudb.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_basic_3tokudb.test
index d600137bec4..4c38646b112 100644
--- a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_basic_3tokudb.test
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_basic_3tokudb.test
@@ -1,11 +1,11 @@
--- source include/have_tokudb.inc
--- source include/have_binlog_format_row.inc
--- source include/master-slave.inc
+--source include/have_tokudb.inc
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
connection slave;
let $bit_field_special = ALL_LOSSY;
-let $type= 'INNODB' ;
-let $extra_index= ;
--- source extra/rpl_tests/rpl_row_basic.test
+let $type = 'TokuDB';
+let $extra_index = ;
+--source extra/rpl_tests/rpl_row_basic.test
--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_commit_after_flush.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_commit_after_flush.test
new file mode 100644
index 00000000000..783bee20307
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_commit_after_flush.test
@@ -0,0 +1,6 @@
+-- source include/not_ndb_default.inc
+-- source include/have_tokudb.inc
+-- source include/master-slave.inc
+let $engine_type=tokudb;
+-- source extra/rpl_tests/rpl_commit_after_flush.test
+--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-master.opt b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-master.opt
new file mode 100644
index 00000000000..d03d176150d
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-master.opt
@@ -0,0 +1 @@
+${?PB_HOST_SPECIFIC_MYSQLD_ARGS}
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-slave.opt b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-slave.opt
new file mode 100644
index 00000000000..d03d176150d
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-slave.opt
@@ -0,0 +1 @@
+${?PB_HOST_SPECIFIC_MYSQLD_ARGS}
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id.test
new file mode 100644
index 00000000000..b14aba2263f
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id.test
@@ -0,0 +1,7 @@
+#################################
+# Wrapper for rpl_insert_id.test#
+#################################
+-- source include/not_ndb_default.inc
+-- source include/have_tokudb.inc
+let $engine_type=tokudb;
+-- source extra/rpl_tests/rpl_insert_id.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id_pk.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id_pk.test
new file mode 100644
index 00000000000..f0302114e5a
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id_pk.test
@@ -0,0 +1,7 @@
+#################################
+# Wrapper for rpl_insert_id.test#
+#################################
+-- source include/not_ndb_default.inc
+-- source include/have_tokudb.inc
+let $engine_type=tokudb;
+-- source extra/rpl_tests/rpl_insert_id_pk.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update.test
new file mode 100644
index 00000000000..06a760ca2a8
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update.test
@@ -0,0 +1,4 @@
+-- source include/not_ndb_default.inc
+-- source include/have_tokudb.inc
+let $engine_type=TokuDB;
+-- source extra/rpl_tests/rpl_multi_update.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2-slave.opt b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2-slave.opt
new file mode 100644
index 00000000000..17d4171af0e
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2-slave.opt
@@ -0,0 +1 @@
+--replicate-ignore-table=nothing.sensible
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2.test
new file mode 100644
index 00000000000..729895d1bbb
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2.test
@@ -0,0 +1,14 @@
+#######################################################
+# Wrapper for rpl_multi_update2.test to allow multi #
+# Engines to reuse test code. By JBM 2006-02-15 #
+# Added comments section and to skip when ndb is #
+# Default engine. #
+#######################################################
+--source include/not_gtid_enabled.inc
+--source include/not_ndb_default.inc
+--source include/have_tokudb.inc
+--source include/master-slave.inc
+call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT');
+let $engine_type=TokuDB;
+--source extra/rpl_tests/rpl_multi_update2.test
+--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update3.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update3.test
new file mode 100644
index 00000000000..18a906664a0
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update3.test
@@ -0,0 +1,13 @@
+#######################################################
+# Wrapper for rpl_multi_update3.test to allow multi #
+# Engines to reuse test code. By JBM 2006-02-15 #
+# Added comments section and to skip when ndb is #
+# Default engine. #
+#######################################################
+--source include/have_tokudb.inc
+--source include/not_ndb_default.inc
+--source include/master-slave.inc
+call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.');
+let $engine_type=TokuDB;
+--source extra/rpl_tests/rpl_multi_update3.test
+--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-master.opt b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-master.opt
new file mode 100644
index 00000000000..e980c2de7ff
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-master.opt
@@ -0,0 +1 @@
+--transaction_isolation=READ-COMMITTED
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-slave.opt b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-slave.opt
new file mode 100644
index 00000000000..264c5c1a4b4
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-slave.opt
@@ -0,0 +1 @@
+--skip-slave-start --relay-log-info-repository=TABLE --relay-log-recovery=1 --transaction_isolation=READ-COMMITTED
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe.test
new file mode 100644
index 00000000000..6bd79691528
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe.test
@@ -0,0 +1,19 @@
+# This test takes long time, so only run it with the --big-test mtr-flag.
+--source include/big_test.inc
+--source include/not_embedded.inc
+--source include/not_valgrind.inc
+--source include/have_debug.inc
+--source include/have_tokudb.inc
+--source include/have_binlog_format_row.inc
+--source include/not_mts_slave_parallel_workers.inc
+--source include/master-slave.inc
+
+call mtr.add_suppression('Attempting backtrace');
+call mtr.add_suppression("Recovery from master pos .* and file master-bin.000001");
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+call mtr.add_suppression(".* InnoDB: Warning: allocated tablespace .*, old maximum was .*");
+
+let $engine_type=TokuDB;
+let $database_name=test;
+--source extra/rpl_tests/rpl_crash_safe.test
+--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.cnf b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.cnf
new file mode 100644
index 00000000000..d758d29f481
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.cnf
@@ -0,0 +1 @@
+!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.test
new file mode 100644
index 00000000000..a52e96dc19d
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.test
@@ -0,0 +1,53 @@
+#Want to skip this test from daily Valgrind execution
+--source include/no_valgrind_without_big.inc
+
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+#
+# This file contains tests for WL#5096.
+#
+
+-- let $rpl_topology= 1->2->3
+-- source include/rpl_init.inc
+-- source include/have_binlog_format_row.inc
+
+#
+# WL#5096 Tests.
+#
+
+#
+# Tests combinations of binlog-row-image against mixes of MyISAM and InnoDB
+# storage engines on all three servers.
+#
+# All the combinarions need not to be separated into their own files as
+# the tests for indexes and engines mixes are, because noblobs test script
+# does not take too long time, thence we do not risk triggering PB2 timeout
+# on valgrind runs.
+#
+
+## NOBLOB
+
+-- let $row_img_set=server_1:NOBLOB:N,server_2:NOBLOB:Y,server_3:NOBLOB:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= extra/rpl_tests/rpl_row_img_blobs.test
+-- source suite/tokudb.rpl/include/rpl_tokudb_row_img_general_loop.inc
+
+## MINIMAL
+
+-- let $row_img_set=server_1:MINIMAL:N,server_2:MINIMAL:Y,server_3:MINIMAL:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= extra/rpl_tests/rpl_row_img_blobs.test
+-- source suite/tokudb.rpl/include/rpl_tokudb_row_img_general_loop.inc
+
+## FULL
+
+-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= extra/rpl_tests/rpl_row_img_blobs.test
+-- source suite/tokudb.rpl/include/rpl_tokudb_row_img_general_loop.inc
+
+
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.cnf b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.cnf
new file mode 100644
index 00000000000..d758d29f481
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.cnf
@@ -0,0 +1 @@
+!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.test
new file mode 100644
index 00000000000..cfbc6519182
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.test
@@ -0,0 +1,50 @@
+#Want to skip this test from daily Valgrind execution
+-- source include/no_valgrind_without_big.inc
+#
+# This file contains tests for WL#5096 and bug fixes.
+#
+
+-- source include/have_binlog_format_row.inc
+-- source include/not_gtid_enabled.inc
+
+-- let $rpl_topology= 1->2->3
+-- source include/rpl_init.inc
+
+-- connection server_1
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_2
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_3
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_1
+
+#
+# WL#5096
+#
+
+#
+# Tests for different storage engines on each server,
+# but same index structure on tables. The tests are conducted
+# using FULL binlog-row-image on all servers.
+#
+
+-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= extra/rpl_tests/rpl_row_img.test
+-- source suite/tokudb.rpl/include/rpl_tokudb_row_img_general_loop.inc
+
+#
+# BUG#49100
+#
+
+-- echo ### Testing with TokuDB storage engine
+
+-- let $engine=TokuDB
+-- source extra/rpl_tests/rpl_row_empty_imgs.test
+
+
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.cnf b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.cnf
new file mode 100644
index 00000000000..d758d29f481
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.cnf
@@ -0,0 +1 @@
+!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.test
new file mode 100644
index 00000000000..4c832208feb
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.test
@@ -0,0 +1,42 @@
+#Want to skip this test from daily Valgrind execution
+-- source include/no_valgrind_without_big.inc
+#
+# This file contains tests for WL#5096 and bug fixes.
+#
+
+-- let $rpl_topology= 1->2->3
+-- source include/rpl_init.inc
+-- source include/have_binlog_format_row.inc
+
+-- connection server_1
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_2
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_3
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_1
+
+#
+# WL#5096
+#
+
+#
+# Tests for different storage engines on each server,
+# but same index structure on tables. The tests are conducted
+# using MINIMAL binlog-row-image on all servers.
+#
+
+-- let $row_img_set=server_1:MINIMAL:N,server_2:MINIMAL:Y,server_3:MINIMAL:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= extra/rpl_tests/rpl_row_img.test
+-- source suite/tokudb.rpl/include/rpl_tokudb_row_img_general_loop.inc
+
+-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+-- source include/rpl_row_img_set.inc
+
+
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.cnf b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.cnf
new file mode 100644
index 00000000000..d758d29f481
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.cnf
@@ -0,0 +1 @@
+!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.test
new file mode 100644
index 00000000000..00b6448ad72
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.test
@@ -0,0 +1,42 @@
+#Want to skip this test from daily Valgrind execution
+-- source include/no_valgrind_without_big.inc
+#
+# This file contains tests for WL#5096 and bug fixes.
+#
+
+-- let $rpl_topology= 1->2->3
+-- source include/rpl_init.inc
+-- source include/have_binlog_format_row.inc
+
+-- connection server_1
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_2
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_3
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_1
+
+#
+# WL#5096
+#
+
+#
+# Tests for different storage engines on each server,
+# but same index structure on tables. The tests are conducted
+# using NOBLOB binlog-row-image on all servers.
+#
+
+-- let $row_img_set=server_1:NOBLOB:N,server_2:NOBLOB:Y,server_3:NOBLOB:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= extra/rpl_tests/rpl_row_img.test
+-- source suite/tokudb.rpl/include/rpl_tokudb_row_img_general_loop.inc
+
+-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+-- source include/rpl_row_img_set.inc
+
+
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.cnf b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.cnf
new file mode 100644
index 00000000000..d758d29f481
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.cnf
@@ -0,0 +1 @@
+!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.test
new file mode 100644
index 00000000000..6f683776c3c
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.test
@@ -0,0 +1,38 @@
+#Want to skip this test from daily Valgrind execution
+-- source include/no_valgrind_without_big.inc
+#
+# This file contains tests for WL#5096.
+#
+
+-- let $rpl_topology= 1->2->3
+-- source include/rpl_init.inc
+-- source include/have_binlog_format_row.inc
+
+-- connection server_1
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_2
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_3
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_1
+
+#
+# WL#5096 Tests.
+#
+
+#
+# Tests FULL image against a mix of MyISAM and InnoDB engines on
+# each of the three servers.
+#
+
+-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= extra/rpl_tests/rpl_row_img_diff_indexes.test
+-- source suite/tokudb.rpl/include/rpl_tokudb_row_img_general_loop.inc
+
+
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.cnf b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.cnf
new file mode 100644
index 00000000000..d758d29f481
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.cnf
@@ -0,0 +1 @@
+!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.test
new file mode 100644
index 00000000000..030bc655291
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.test
@@ -0,0 +1,41 @@
+#Want to skip this test from daily Valgrind execution
+--source include/no_valgrind_without_big.inc
+#
+# This file contains tests for WL#5096.
+#
+
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+-- source include/have_binlog_format_row.inc
+
+-- connection server_1
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_2
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_3
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_1
+
+#
+# WL#5096 Tests.
+#
+
+#
+# Tests MINIMAL image against a mix of MyISAM and InnoDB engines on
+# each of the three servers.
+#
+
+-- let $row_img_set=server_1:MINIMAL:N,server_2:MINIMAL:Y,server_3:MINIMAL:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= extra/rpl_tests/rpl_row_img_diff_indexes.test
+-- source suite/tokudb.rpl/include/rpl_tokudb_row_img_general_loop.inc
+
+-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+-- source include/rpl_row_img_set.inc
+
+
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.cnf b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.cnf
new file mode 100644
index 00000000000..d758d29f481
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.cnf
@@ -0,0 +1 @@
+!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.test
new file mode 100644
index 00000000000..785f79bccdc
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.test
@@ -0,0 +1,41 @@
+#Want to skip this test from daily Valgrind execution
+-- source include/no_valgrind_without_big.inc
+#
+# This file contains tests for WL#5096.
+#
+
+-- let $rpl_topology= 1->2->3
+-- source include/rpl_init.inc
+-- source include/have_binlog_format_row.inc
+
+-- connection server_1
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_2
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_3
+-- source include/have_innodb.inc
+-- source include/have_tokudb.inc
+-- connection server_1
+
+#
+# WL#5096
+#
+
+#
+# Tests NOBLOB image against a mix of MyISAM and InnoDB engines on
+# each of the three servers.
+#
+
+-- let $row_img_set=server_1:NOBLOB:N,server_2:NOBLOB:Y,server_3:NOBLOB:Y
+-- source include/rpl_row_img_set.inc
+
+-- let $row_img_test_script= extra/rpl_tests/rpl_row_img_diff_indexes.test
+-- source suite/tokudb.rpl/include/rpl_tokudb_row_img_general_loop.inc
+
+-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y
+-- source include/rpl_row_img_set.inc
+
+
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log-master.opt b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log-master.opt
new file mode 100644
index 00000000000..773ec62bef2
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log-master.opt
@@ -0,0 +1,2 @@
+--skip-external-locking
+--default-storage-engine=MyISAM
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log.test
new file mode 100644
index 00000000000..bc624d4d89c
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log.test
@@ -0,0 +1,15 @@
+###################################
+# Wrapper for rpl_row_log.test #
+# Added wrapper so that MyISAM & #
+# Innodb and NDB could all use the#
+# Same test. NDB produced a diff #
+# bin-log #
+###################################
+-- source include/not_ndb_default.inc
+-- source include/have_binlog_format_row.inc
+-- source include/have_tokudb.inc
+-- source include/master-slave.inc
+let $engine_type=TokuDB;
+-- source extra/rpl_tests/rpl_log.test
+
+--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names-slave.opt b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names-slave.opt
new file mode 100644
index 00000000000..8be29bbe976
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names-slave.opt
@@ -0,0 +1 @@
+--replicate-do-db=bug_37656 --replicate-ignore-table=bug_37656.t1 --replicate-do-table=bug_37656.t2 --replicate-do-table=bug_37656.t3 --lower-case-table-names=1
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names.test
new file mode 100644
index 00000000000..56599f3c1ad
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names.test
@@ -0,0 +1,14 @@
+# BUG#37656
+#
+# For details look into extra/rpl_tests/rpl_lower_case_table_names.test
+#
+
+-- source include/not_gtid_enabled.inc
+-- source include/have_tokudb.inc
+-- source include/not_windows.inc
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+
+-- let $engine=TokuDB
+-- source extra/rpl_tests/rpl_lower_case_table_names.test
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp003.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp003.test
new file mode 100644
index 00000000000..38ea65061fe
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp003.test
@@ -0,0 +1,14 @@
+#################################
+# Wrapper for rpl_row_sp003.test#
+#################################
+########################################################
+# By JBM 2005-02-15 Wrapped to allow reuse of test code#
+# Added to skip if ndb is default #
+########################################################
+-- source include/not_ndb_default.inc
+-- source include/have_tokudb.inc
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+let $engine_type=TOKUDB;
+-- source extra/rpl_tests/rpl_row_sp003.test
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp006.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp006.test
new file mode 100644
index 00000000000..41eececc198
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp006.test
@@ -0,0 +1,14 @@
+#################################
+# Wrapper for rpl_row_sp006.test#
+#################################
+########################################################
+# By JBM 2005-02-15 Wrapped to allow reuse of test code#
+# Added to skip if ndb is default #
+########################################################
+-- source include/not_ndb_default.inc
+-- source include/have_tokudb.inc
+-- source include/have_binlog_format_row.inc
+-- source include/master-slave.inc
+let $engine_type=TokuDB;
+-- source extra/rpl_tests/rpl_row_sp006.test
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_trig004.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_trig004.test
new file mode 100644
index 00000000000..ad4ea1a2a57
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_trig004.test
@@ -0,0 +1,19 @@
+#############################################################################
+# Original Author: JBM #
+# Original Date: Oct/18/2005 #
+#############################################################################
+# TEST: Use before insert triggers and has the second insert fail #
+#############################################################################
+# Change by JBM 2006-02-14 added to skip when NDB default engine #
+# This test has been wrapped to allow multipal engines to use same code #
+#############################################################################
+
+# Includes
+-- source include/not_ndb_default.inc
+-- source include/have_binlog_format_row.inc
+-- source include/have_tokudb.inc
+-- source include/master-slave.inc
+let $engine_type=TOKUDB;
+-- source extra/rpl_tests/rpl_trig004.test
+
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log-master.opt b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log-master.opt
new file mode 100644
index 00000000000..773ec62bef2
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log-master.opt
@@ -0,0 +1,2 @@
+--skip-external-locking
+--default-storage-engine=MyISAM
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log.test
new file mode 100644
index 00000000000..42eb4961dce
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log.test
@@ -0,0 +1,15 @@
+###################################
+# Wrapper for rpl_row_log.test #
+# Added wrapper so that MyISAM & #
+# Innodb and NDB could all use the#
+# Same test. NDB produced a diff #
+# bin-log #
+###################################
+-- source include/not_ndb_default.inc
+-- source include/have_binlog_format_statement.inc
+-- source include/have_tokudb.inc
+-- source include/master-slave.inc
+let $engine_type=TokuDB;
+-- source extra/rpl_tests/rpl_log.test
+
+--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-master.opt b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-master.opt
new file mode 100644
index 00000000000..e980c2de7ff
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-master.opt
@@ -0,0 +1 @@
+--transaction_isolation=READ-COMMITTED
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-slave.opt b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-slave.opt
new file mode 100644
index 00000000000..264c5c1a4b4
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-slave.opt
@@ -0,0 +1 @@
+--skip-slave-start --relay-log-info-repository=TABLE --relay-log-recovery=1 --transaction_isolation=READ-COMMITTED
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe.test
new file mode 100644
index 00000000000..724550fae4a
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe.test
@@ -0,0 +1,18 @@
+--source include/big_test.inc
+--source include/not_embedded.inc
+--source include/not_valgrind.inc
+--source include/have_debug.inc
+--source include/have_tokudb.inc
+--source include/have_binlog_format_mixed_or_statement.inc
+--source include/not_mts_slave_parallel_workers.inc
+--source include/master-slave.inc
+
+call mtr.add_suppression('Attempting backtrace');
+call mtr.add_suppression("Recovery from master pos .* and file master-bin.000001");
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+call mtr.add_suppression(".* InnoDB: Warning: allocated tablespace .*, old maximum was .*");
+
+let $engine_type=TokuDB;
+let $database_name=test;
+--source extra/rpl_tests/rpl_crash_safe.test
+--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names-slave.opt b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names-slave.opt
new file mode 100644
index 00000000000..8be29bbe976
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names-slave.opt
@@ -0,0 +1 @@
+--replicate-do-db=bug_37656 --replicate-ignore-table=bug_37656.t1 --replicate-do-table=bug_37656.t2 --replicate-do-table=bug_37656.t3 --lower-case-table-names=1
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names.test b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names.test
new file mode 100644
index 00000000000..2a7e690f27a
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names.test
@@ -0,0 +1,14 @@
+# BUG#37656
+#
+# For details look into extra/rpl_tests/rpl_lower_case_table_names.test
+#
+
+-- source include/not_gtid_enabled.inc
+-- source include/have_tokudb.inc
+-- source include/not_windows.inc
+-- source include/have_binlog_format_mixed_or_statement.inc
+-- source include/master-slave.inc
+
+-- let $engine=TokuDB
+-- source extra/rpl_tests/rpl_lower_case_table_names.test
+-- source include/rpl_end.inc
diff --git a/storage/tokudb/tokudb_information_schema.cc b/storage/tokudb/tokudb_information_schema.cc
index 6cdd9b275fb..fb9e76f340b 100644
--- a/storage/tokudb/tokudb_information_schema.cc
+++ b/storage/tokudb/tokudb_information_schema.cc
@@ -73,7 +73,8 @@ int trx_callback(
void *extra) {
uint64_t txn_id = txn->id64(txn);
- uint64_t client_id = txn->get_client_id(txn);
+ uint64_t client_id;
+ txn->get_client_id(txn, &client_id, NULL);
uint64_t start_time = txn->get_start_time(txn);
trx_extra_t* e = reinterpret_cast(extra);
THD* thd = e->thd;
@@ -312,7 +313,8 @@ int locks_callback(
void* extra) {
uint64_t txn_id = txn->id64(txn);
- uint64_t client_id = txn->get_client_id(txn);
+ uint64_t client_id;
+ txn->get_client_id(txn, &client_id, NULL);
locks_extra_t* e = reinterpret_cast(extra);
THD* thd = e->thd;
TABLE* table = e->table;
diff --git a/storage/tokudb/tokudb_txn.h b/storage/tokudb/tokudb_txn.h
index 67bf591d088..d0255415403 100644
--- a/storage/tokudb/tokudb_txn.h
+++ b/storage/tokudb/tokudb_txn.h
@@ -116,7 +116,7 @@ inline int txn_begin(
int r = env->txn_begin(env, parent, txn, flags);
if (r == 0 && thd) {
DB_TXN* this_txn = *txn;
- this_txn->set_client_id(this_txn, thd_get_thread_id(thd));
+ this_txn->set_client_id(this_txn, thd_get_thread_id(thd), thd);
}
TOKUDB_TRACE_FOR_FLAGS(
TOKUDB_DEBUG_TXN,
From 13e4bf674e26065cefce6746c7c52afdad5ce8ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Wed, 2 Aug 2017 19:05:48 +0300
Subject: [PATCH 095/101] Fix tokudb compilation post merge
---
storage/tokudb/PerconaFT/portability/toku_debug_sync.h | 2 +-
storage/tokudb/PerconaFT/tools/CMakeLists.txt | 2 +-
storage/tokudb/hatoku_hton.cc | 7 ++++---
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/storage/tokudb/PerconaFT/portability/toku_debug_sync.h b/storage/tokudb/PerconaFT/portability/toku_debug_sync.h
index 4a959cab1fe..b5394e58d68 100644
--- a/storage/tokudb/PerconaFT/portability/toku_debug_sync.h
+++ b/storage/tokudb/PerconaFT/portability/toku_debug_sync.h
@@ -67,7 +67,7 @@ inline void toku_debug_sync(struct tokutxn *txn, const char *sync_point_name) {
toku_txn_get_client_id(txn, &client_id, &client_extra);
thd = reinterpret_cast(client_extra);
- debug_sync(thd, sync_point_name, strlen(sync_point_name));
+ DEBUG_SYNC(thd, sync_point_name);
}
#else // defined(ENABLED_DEBUG_SYNC)
diff --git a/storage/tokudb/PerconaFT/tools/CMakeLists.txt b/storage/tokudb/PerconaFT/tools/CMakeLists.txt
index daaff5eb379..e6540bf69be 100644
--- a/storage/tokudb/PerconaFT/tools/CMakeLists.txt
+++ b/storage/tokudb/PerconaFT/tools/CMakeLists.txt
@@ -10,7 +10,7 @@ foreach(tool ${tools})
if (DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
if ((CMAKE_BUILD_TYPE MATCHES "Debug") AND
(CMAKE_CXX_FLAGS_DEBUG MATCHES " -DENABLED_DEBUG_SYNC"))
- target_link_libraries(${tool} sql binlog rpl master slave)
+ target_link_libraries(${tool} sql)
endif()
endif ()
diff --git a/storage/tokudb/hatoku_hton.cc b/storage/tokudb/hatoku_hton.cc
index e0f92b17fce..76ce6bec0fc 100644
--- a/storage/tokudb/hatoku_hton.cc
+++ b/storage/tokudb/hatoku_hton.cc
@@ -55,7 +55,7 @@ static bool tokudb_show_status(
static void tokudb_handle_fatal_signal(handlerton* hton, THD* thd, int sig);
#endif
static int tokudb_close_connection(handlerton* hton, THD* thd);
-static void tokudb_kill_connection(handlerton *hton, THD *thd);
+static void tokudb_kill_connection(handlerton *hton, THD *thd, enum thd_kill_levels level);
static int tokudb_commit(handlerton* hton, THD* thd, bool all);
static int tokudb_rollback(handlerton* hton, THD* thd, bool all);
#if TOKU_INCLUDE_XA
@@ -332,7 +332,7 @@ static int tokudb_init_func(void *p) {
tokudb_hton->create = tokudb_create_handler;
tokudb_hton->close_connection = tokudb_close_connection;
- tokudb_hton->kill_connection = tokudb_kill_connection;
+ tokudb_hton->kill_query = tokudb_kill_connection;
tokudb_hton->savepoint_offset = sizeof(SP_INFO_T);
tokudb_hton->savepoint_set = tokudb_savepoint;
@@ -756,7 +756,8 @@ static int tokudb_close_connection(handlerton* hton, THD* thd) {
return error;
}
-void tokudb_kill_connection(handlerton *hton, THD *thd) {
+void tokudb_kill_connection(handlerton *hton, THD *thd,
+ enum thd_kill_levels level) {
TOKUDB_DBUG_ENTER("");
db_env->kill_waiter(db_env, thd);
DBUG_VOID_RETURN;
From e35670f49804399a208671901fd6f755647c49e2 Mon Sep 17 00:00:00 2001
From: Monty
Date: Thu, 3 Aug 2017 19:28:05 +0300
Subject: [PATCH 096/101] MDEV-12972 Random and Frequent Segfault
Problem was a memory overflow in MRR
Reviewed by Sergei Petruna. Testcase by Elena
---
sql/multi_range_read.cc | 22 +++++-----------
.../tokudb_mariadb/r/mdev12972.result | 19 ++++++++++++++
.../tokudb_mariadb/t/mdev12972.test | 26 +++++++++++++++++++
3 files changed, 51 insertions(+), 16 deletions(-)
create mode 100644 storage/tokudb/mysql-test/tokudb_mariadb/r/mdev12972.result
create mode 100644 storage/tokudb/mysql-test/tokudb_mariadb/t/mdev12972.test
diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc
index e856400466d..1b79f815a0f 100644
--- a/sql/multi_range_read.cc
+++ b/sql/multi_range_read.cc
@@ -1231,28 +1231,18 @@ bool DsMrr_impl::setup_buffer_sharing(uint key_size_in_keybuf,
ptrdiff_t bytes_for_keys= (full_buf_end - full_buf) - bytes_for_rowids;
- if (bytes_for_keys < key_buff_elem_size + 1)
- {
- ptrdiff_t add= key_buff_elem_size + 1 - bytes_for_keys;
- bytes_for_keys= key_buff_elem_size + 1;
- bytes_for_rowids -= add;
- }
-
- if (bytes_for_rowids < (ptrdiff_t)rowid_buf_elem_size + 1)
- {
- ptrdiff_t add= (ptrdiff_t)(rowid_buf_elem_size + 1 - bytes_for_rowids);
- bytes_for_rowids= (ptrdiff_t)rowid_buf_elem_size + 1;
- bytes_for_keys -= add;
- }
+ if (bytes_for_keys < key_buff_elem_size + 1 ||
+ bytes_for_rowids < (ptrdiff_t)rowid_buf_elem_size + 1)
+ return TRUE; /* Failed to provide minimum space for one of the buffers */
rowid_buffer_end= full_buf + bytes_for_rowids;
rowid_buffer.set_buffer_space(full_buf, rowid_buffer_end);
key_buffer= &backward_key_buf;
key_buffer->set_buffer_space(rowid_buffer_end, full_buf_end);
- if (!key_buffer->have_space_for(key_buff_elem_size) ||
- !rowid_buffer.have_space_for((size_t)rowid_buf_elem_size))
- return TRUE; /* Failed to provide minimum space for one of the buffers */
+ /* The above code guarantees that the buffers are big enough */
+ DBUG_ASSERT(key_buffer->have_space_for(key_buff_elem_size) &&
+ rowid_buffer.have_space_for((size_t)rowid_buf_elem_size));
return FALSE;
}
diff --git a/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev12972.result b/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev12972.result
new file mode 100644
index 00000000000..fce77f1647d
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev12972.result
@@ -0,0 +1,19 @@
+CREATE TABLE t1 (pk INT PRIMARY KEY, i1 INT, c1 VARCHAR(1), KEY(c1)) ENGINE=TokuDB;
+INSERT INTO t1 VALUES
+(1,2,NULL),(2,5,'x'),(3,3,'i'),(4,1,'e'),(5,4,'p');
+CREATE TABLE t2 (i2 INT) ENGINE=TokuDB;
+INSERT INTO t2 VALUES (1),(2);
+CREATE TABLE t3 (i3 INT, c3 VARCHAR(1), KEY(i3)) ENGINE=TokuDB;
+INSERT INTO t3 VALUES
+(1,'e'),(1,'z'),(1,'i'),(1,'q'),(1,'i'),(1,'f'),(1,'m'),(2,'c'),(1,'d'),
+(2,'n'),(1,'t'),(2,'e'),(1,'w'),(2,'y'),(1,'j'),(2,'i'),(1,'f'),(2,'f'),
+(1,'s'),(2,'y');
+SET join_cache_level = 8;
+SET optimizer_switch ='mrr=on,mrr_sort_keys=on,optimize_join_buffer_size=on';
+SELECT * FROM t1 AS t1_outer WHERE EXISTS ( SELECT * FROM t2 WHERE i2 IN ( SELECT i3 FROM t3 INNER JOIN t1 AS t1_inner ON (t1_inner.c1 = c3 ) WHERE t1_inner.i1 < t1_outer.i1 ) );
+pk i1 c1
+1 2 NULL
+2 5 x
+3 3 i
+5 4 p
+DROP TABLE t1, t2, t3;
diff --git a/storage/tokudb/mysql-test/tokudb_mariadb/t/mdev12972.test b/storage/tokudb/mysql-test/tokudb_mariadb/t/mdev12972.test
new file mode 100644
index 00000000000..9d136ff0c65
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_mariadb/t/mdev12972.test
@@ -0,0 +1,26 @@
+#
+# MDEV-12972 Random and Frequent Segfault (SIG 11) During Runtime
+#
+# This was actually a memory overrun in MRR that TokuDB triggered
+#
+
+CREATE TABLE t1 (pk INT PRIMARY KEY, i1 INT, c1 VARCHAR(1), KEY(c1)) ENGINE=TokuDB;
+INSERT INTO t1 VALUES
+(1,2,NULL),(2,5,'x'),(3,3,'i'),(4,1,'e'),(5,4,'p');
+
+CREATE TABLE t2 (i2 INT) ENGINE=TokuDB;
+INSERT INTO t2 VALUES (1),(2);
+
+CREATE TABLE t3 (i3 INT, c3 VARCHAR(1), KEY(i3)) ENGINE=TokuDB;
+INSERT INTO t3 VALUES
+(1,'e'),(1,'z'),(1,'i'),(1,'q'),(1,'i'),(1,'f'),(1,'m'),(2,'c'),(1,'d'),
+(2,'n'),(1,'t'),(2,'e'),(1,'w'),(2,'y'),(1,'j'),(2,'i'),(1,'f'),(2,'f'),
+(1,'s'),(2,'y');
+
+SET join_cache_level = 8;
+SET optimizer_switch ='mrr=on,mrr_sort_keys=on,optimize_join_buffer_size=on';
+
+--sorted_result
+SELECT * FROM t1 AS t1_outer WHERE EXISTS ( SELECT * FROM t2 WHERE i2 IN ( SELECT i3 FROM t3 INNER JOIN t1 AS t1_inner ON (t1_inner.c1 = c3 ) WHERE t1_inner.i1 < t1_outer.i1 ) );
+
+DROP TABLE t1, t2, t3;
From d5164569e46a927a83b9789d98a7ca5bc71eb116 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Thu, 3 Aug 2017 22:15:19 +0300
Subject: [PATCH 097/101] Move tokudb_rpl to rpl-tokudb suite
---
storage/tokudb/mysql-test/{tokudb_rpl => rpl}/combinations | 0
.../include/rpl_tokudb_row_img_general_loop.inc | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_deadlock_tokudb.result | 0
.../{tokudb_rpl => rpl}/r/rpl_extra_col_master_tokudb.result | 0
.../{tokudb_rpl => rpl}/r/rpl_extra_col_slave_tokudb.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_mixed_row_tokudb.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_not_null_tokudb.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_parallel_tokudb.result | 0
.../{tokudb_rpl => rpl}/r/rpl_parallel_tokudb_delete_pk.result | 0
.../r/rpl_parallel_tokudb_update_pk_uc0_lookup0.result | 0
.../{tokudb_rpl => rpl}/r/rpl_parallel_tokudb_write_pk.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_partition_tokudb.result | 0
.../{tokudb_rpl => rpl}/r/rpl_relay_space_tokudb.result | 0
.../r/rpl_rfr_disable_on_expl_pk_absence.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_row_basic_3tokudb.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_row_blob_tokudb.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_row_log_tokudb.result | 0
.../{tokudb_rpl => rpl}/r/rpl_row_rec_comp_tokudb.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_row_sp002_tokudb.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_row_sp007_tokudb.result | 0
.../{tokudb_rpl => rpl}/r/rpl_row_tabledefs_3tokudb.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_set_null_tokudb.result | 0
.../tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_stm_tokudb.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_bug28430.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_bug30888.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_commit_after_flush.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_delete_pk.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_delete_pk_lookup1.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_insert_id.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_insert_id_pk.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_mixed_ddl.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_mixed_dml.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_multi_update.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_multi_update2.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_multi_update3.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_read_only_ff.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_read_only_ft.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_read_only_tf.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_read_only_tt.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_rfr_partition_table.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_row_crash_safe.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_blobs.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_eng_full.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_eng_min.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_eng_noblob.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_idx_full.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_idx_min.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_idx_noblob.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_log.result | 0
.../r/rpl_tokudb_row_lower_case_table_names.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_sp003.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_sp006.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_row_trig004.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_stm_log.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_stm_mixed_crash_safe.result | 0
.../r/rpl_tokudb_stm_mixed_lower_case_table_names.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_update_pk_uc0_lookup0.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_update_pk_uc0_lookup1.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_update_pk_uc1_lookup0.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_update_pk_uc1_lookup1.result | 0
.../r/rpl_tokudb_update_unique_uc0_lookup0.result | 0
.../r/rpl_tokudb_update_unique_uc0_lookup1.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_write_pk.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_write_pk_uc1.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_write_unique.result | 0
.../{tokudb_rpl => rpl}/r/rpl_tokudb_write_unique_uc1.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_truncate_3tokudb.result | 0
.../mysql-test/{tokudb_rpl => rpl}/r/rpl_typeconv_tokudb.result | 0
.../{tokudb_rpl => rpl}/r/tokudb_innodb_xa_crash.result | 0
storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/disabled.def | 0
.../{tokudb_rpl => rpl}/t/rpl_deadlock_tokudb-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_deadlock_tokudb.test | 0
.../{tokudb_rpl => rpl}/t/rpl_extra_col_master_tokudb.test | 0
.../{tokudb_rpl => rpl}/t/rpl_extra_col_slave_tokudb.test | 0
.../{tokudb_rpl => rpl}/t/rpl_mixed_row_tokudb-master.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_not_null_tokudb.test | 0
.../{tokudb_rpl => rpl}/t/rpl_parallel_tokudb-master.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_parallel_tokudb-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_parallel_tokudb.test | 0
.../{tokudb_rpl => rpl}/t/rpl_parallel_tokudb_delete_pk-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_parallel_tokudb_delete_pk.test | 0
.../t/rpl_parallel_tokudb_update_pk_uc0_lookup0-slave.opt | 0
.../t/rpl_parallel_tokudb_update_pk_uc0_lookup0.test | 0
.../{tokudb_rpl => rpl}/t/rpl_parallel_tokudb_write_pk-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_parallel_tokudb_write_pk.test | 0
.../{tokudb_rpl => rpl}/t/rpl_partition_tokudb-master.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_partition_tokudb.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_relay_space_tokudb.test | 0
.../t/rpl_rfr_disable_on_expl_pk_absence-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_rfr_disable_on_expl_pk_absence.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_row_basic_3tokudb.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_row_blob_tokudb.test | 0
.../{tokudb_rpl => rpl}/t/rpl_row_log_tokudb-master.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_row_log_tokudb.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_row_rec_comp_tokudb.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_row_sp002_tokudb.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_row_sp007_tokudb.test | 0
.../{tokudb_rpl => rpl}/t/rpl_row_tabledefs_3tokudb.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_set_null_tokudb.test | 0
.../tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_stm_tokudb.test | 0
.../tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb-master.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_bug28430-master.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_bug28430-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_bug28430.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_bug30888.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_commit_after_flush.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_delete_pk-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_delete_pk.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_delete_pk_lookup1-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_delete_pk_lookup1.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_insert_id-master.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_insert_id-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_insert_id.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_insert_id_pk.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_mixed_ddl.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_mixed_dml.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_multi_update.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_multi_update2-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_multi_update2.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_multi_update3.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_ff-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_ff.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_ft-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_ft.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_tf-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_tf.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_tt-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_tt.test | 0
.../t/rpl_tokudb_rfr_partition_table-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_rfr_partition_table.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_crash_safe-master.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_crash_safe-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_crash_safe.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_blobs.cnf | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_blobs.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_full.cnf | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_full.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_min.cnf | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_min.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_noblob.cnf | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_noblob.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_full.cnf | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_full.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_min.cnf | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_min.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_noblob.cnf | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_noblob.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_row_log-master.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_log.test | 0
.../t/rpl_tokudb_row_lower_case_table_names-slave.opt | 0
.../t/rpl_tokudb_row_lower_case_table_names.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_sp003.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_sp006.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_trig004.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_stm_log-master.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_stm_log.test | 0
.../t/rpl_tokudb_stm_mixed_crash_safe-master.opt | 0
.../t/rpl_tokudb_stm_mixed_crash_safe-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_stm_mixed_crash_safe.test | 0
.../t/rpl_tokudb_stm_mixed_lower_case_table_names-slave.opt | 0
.../t/rpl_tokudb_stm_mixed_lower_case_table_names.test | 0
.../t/rpl_tokudb_update_pk_uc0_lookup0-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc0_lookup0.test | 0
.../t/rpl_tokudb_update_pk_uc0_lookup1-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc0_lookup1.test | 0
.../t/rpl_tokudb_update_pk_uc1_lookup0-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc1_lookup0.test | 0
.../t/rpl_tokudb_update_pk_uc1_lookup1-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc1_lookup1.test | 0
.../t/rpl_tokudb_update_unique_uc0_lookup0-slave.opt | 0
.../t/rpl_tokudb_update_unique_uc0_lookup0.test | 0
.../t/rpl_tokudb_update_unique_uc0_lookup1-slave.opt | 0
.../t/rpl_tokudb_update_unique_uc0_lookup1.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_write_pk-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_write_pk.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_write_pk_uc1-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_write_pk_uc1.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_write_unique-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_write_unique.test | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_write_unique_uc1-slave.opt | 0
.../{tokudb_rpl => rpl}/t/rpl_tokudb_write_unique_uc1.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_truncate_3tokudb.test | 0
.../mysql-test/{tokudb_rpl => rpl}/t/rpl_typeconv_tokudb.test | 0
storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/suite.opt | 0
.../{tokudb_rpl => rpl}/t/tokudb_innodb_xa_crash-slave.opt | 0
.../mysql-test/{tokudb_rpl => rpl}/t/tokudb_innodb_xa_crash.test | 0
186 files changed, 0 insertions(+), 0 deletions(-)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/combinations (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/include/rpl_tokudb_row_img_general_loop.inc (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_deadlock_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_extra_col_master_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_extra_col_slave_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_mixed_row_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_not_null_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_parallel_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_parallel_tokudb_delete_pk.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_parallel_tokudb_update_pk_uc0_lookup0.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_parallel_tokudb_write_pk.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_partition_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_relay_space_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_rfr_disable_on_expl_pk_absence.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_row_basic_3tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_row_blob_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_row_log_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_row_rec_comp_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_row_sp002_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_row_sp007_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_row_tabledefs_3tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_set_null_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_stm_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_bug28430.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_bug30888.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_commit_after_flush.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_delete_pk.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_delete_pk_lookup1.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_insert_id.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_insert_id_pk.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_mixed_ddl.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_mixed_dml.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_multi_update.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_multi_update2.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_multi_update3.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_read_only_ff.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_read_only_ft.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_read_only_tf.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_read_only_tt.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_rfr_partition_table.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_crash_safe.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_blobs.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_eng_full.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_eng_min.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_eng_noblob.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_idx_full.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_idx_min.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_img_idx_noblob.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_log.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_lower_case_table_names.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_sp003.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_sp006.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_row_trig004.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_stm_log.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_stm_mixed_crash_safe.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_stm_mixed_lower_case_table_names.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_update_pk_uc0_lookup0.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_update_pk_uc0_lookup1.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_update_pk_uc1_lookup0.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_update_pk_uc1_lookup1.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_update_unique_uc0_lookup0.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_update_unique_uc0_lookup1.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_write_pk.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_write_pk_uc1.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_write_unique.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_tokudb_write_unique_uc1.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_truncate_3tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/rpl_typeconv_tokudb.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/r/tokudb_innodb_xa_crash.result (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/disabled.def (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_deadlock_tokudb-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_deadlock_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_extra_col_master_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_extra_col_slave_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_mixed_row_tokudb-master.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_not_null_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_parallel_tokudb-master.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_parallel_tokudb-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_parallel_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_parallel_tokudb_delete_pk-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_parallel_tokudb_delete_pk.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_parallel_tokudb_update_pk_uc0_lookup0-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_parallel_tokudb_update_pk_uc0_lookup0.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_parallel_tokudb_write_pk-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_parallel_tokudb_write_pk.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_partition_tokudb-master.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_partition_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_relay_space_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_rfr_disable_on_expl_pk_absence-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_rfr_disable_on_expl_pk_absence.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_row_basic_3tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_row_blob_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_row_log_tokudb-master.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_row_log_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_row_rec_comp_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_row_sp002_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_row_sp007_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_row_tabledefs_3tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_set_null_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_stm_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb-master.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_bug28430-master.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_bug28430-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_bug28430.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_bug30888.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_commit_after_flush.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_delete_pk-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_delete_pk.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_delete_pk_lookup1-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_delete_pk_lookup1.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_insert_id-master.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_insert_id-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_insert_id.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_insert_id_pk.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_mixed_ddl.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_mixed_dml.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_multi_update.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_multi_update2-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_multi_update2.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_multi_update3.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_ff-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_ff.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_ft-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_ft.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_tf-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_tf.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_tt-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_read_only_tt.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_rfr_partition_table-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_rfr_partition_table.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_crash_safe-master.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_crash_safe-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_crash_safe.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_blobs.cnf (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_blobs.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_full.cnf (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_full.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_min.cnf (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_min.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_noblob.cnf (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_eng_noblob.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_full.cnf (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_full.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_min.cnf (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_min.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_noblob.cnf (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_img_idx_noblob.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_log-master.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_log.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_lower_case_table_names-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_lower_case_table_names.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_sp003.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_sp006.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_row_trig004.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_stm_log-master.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_stm_log.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_stm_mixed_crash_safe-master.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_stm_mixed_crash_safe-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_stm_mixed_crash_safe.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_stm_mixed_lower_case_table_names-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_stm_mixed_lower_case_table_names.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc0_lookup0-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc0_lookup0.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc0_lookup1-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc0_lookup1.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc1_lookup0-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc1_lookup0.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc1_lookup1-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_pk_uc1_lookup1.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_unique_uc0_lookup0-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_unique_uc0_lookup0.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_unique_uc0_lookup1-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_update_unique_uc0_lookup1.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_write_pk-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_write_pk.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_write_pk_uc1-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_write_pk_uc1.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_write_unique-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_write_unique.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_write_unique_uc1-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_tokudb_write_unique_uc1.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_truncate_3tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/rpl_typeconv_tokudb.test (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/suite.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/tokudb_innodb_xa_crash-slave.opt (100%)
rename storage/tokudb/mysql-test/{tokudb_rpl => rpl}/t/tokudb_innodb_xa_crash.test (100%)
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/combinations b/storage/tokudb/mysql-test/rpl/combinations
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/combinations
rename to storage/tokudb/mysql-test/rpl/combinations
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/include/rpl_tokudb_row_img_general_loop.inc b/storage/tokudb/mysql-test/rpl/include/rpl_tokudb_row_img_general_loop.inc
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/include/rpl_tokudb_row_img_general_loop.inc
rename to storage/tokudb/mysql-test/rpl/include/rpl_tokudb_row_img_general_loop.inc
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_deadlock_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_deadlock_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_deadlock_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_deadlock_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_extra_col_master_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_master_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_extra_col_master_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_extra_col_master_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_extra_col_slave_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_slave_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_extra_col_slave_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_extra_col_slave_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_mixed_row_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_mixed_row_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_mixed_row_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_mixed_row_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_not_null_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_not_null_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_not_null_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_not_null_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_parallel_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_parallel_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_parallel_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_parallel_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_parallel_tokudb_delete_pk.result b/storage/tokudb/mysql-test/rpl/r/rpl_parallel_tokudb_delete_pk.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_parallel_tokudb_delete_pk.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_parallel_tokudb_delete_pk.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_parallel_tokudb_update_pk_uc0_lookup0.result b/storage/tokudb/mysql-test/rpl/r/rpl_parallel_tokudb_update_pk_uc0_lookup0.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_parallel_tokudb_update_pk_uc0_lookup0.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_parallel_tokudb_update_pk_uc0_lookup0.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_parallel_tokudb_write_pk.result b/storage/tokudb/mysql-test/rpl/r/rpl_parallel_tokudb_write_pk.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_parallel_tokudb_write_pk.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_parallel_tokudb_write_pk.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_partition_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_partition_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_partition_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_partition_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_relay_space_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_relay_space_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_relay_space_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_relay_space_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_rfr_disable_on_expl_pk_absence.result b/storage/tokudb/mysql-test/rpl/r/rpl_rfr_disable_on_expl_pk_absence.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_rfr_disable_on_expl_pk_absence.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_rfr_disable_on_expl_pk_absence.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_basic_3tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_row_basic_3tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_basic_3tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_row_basic_3tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_blob_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_row_blob_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_blob_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_row_blob_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_log_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_row_log_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_log_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_row_log_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_rec_comp_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_row_rec_comp_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_rec_comp_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_row_rec_comp_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_sp002_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_row_sp002_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_sp002_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_row_sp002_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_sp007_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_row_sp007_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_sp007_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_row_sp007_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_tabledefs_3tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_row_tabledefs_3tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_row_tabledefs_3tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_row_tabledefs_3tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_set_null_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_set_null_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_set_null_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_set_null_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_stm_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_stm_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_stm_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_stm_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_bug28430.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug28430.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_bug28430.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug28430.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_bug30888.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug30888.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_bug30888.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug30888.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_commit_after_flush.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_commit_after_flush.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_commit_after_flush.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_commit_after_flush.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_delete_pk.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_delete_pk.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_delete_pk.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_delete_pk.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_delete_pk_lookup1.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_delete_pk_lookup1.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_delete_pk_lookup1.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_delete_pk_lookup1.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_insert_id.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_insert_id.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id_pk.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_insert_id_pk.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_insert_id_pk.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_insert_id_pk.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_mixed_ddl.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_ddl.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_mixed_ddl.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_ddl.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_mixed_dml.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_dml.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_mixed_dml.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_dml.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_multi_update.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_multi_update.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update2.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_multi_update2.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update2.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_multi_update2.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update3.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_multi_update3.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_multi_update3.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_multi_update3.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_read_only_ff.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ff.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_read_only_ff.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ff.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_read_only_ft.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_read_only_ft.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_read_only_tf.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tf.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_read_only_tf.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tf.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_read_only_tt.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tt.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_read_only_tt.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tt.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_rfr_partition_table.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_rfr_partition_table.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_rfr_partition_table.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_rfr_partition_table.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_crash_safe.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_crash_safe.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_crash_safe.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_crash_safe.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_blobs.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_blobs.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_blobs.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_blobs.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_full.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_eng_full.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_full.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_eng_full.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_min.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_eng_min.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_min.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_eng_min.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_noblob.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_eng_noblob.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_eng_noblob.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_eng_noblob.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_full.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_idx_full.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_full.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_idx_full.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_min.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_idx_min.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_min.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_idx_min.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_noblob.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_idx_noblob.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_img_idx_noblob.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_img_idx_noblob.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_log.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_log.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_log.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_log.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_lower_case_table_names.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_lower_case_table_names.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_lower_case_table_names.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_lower_case_table_names.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp003.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_sp003.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp003.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_sp003.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp006.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_sp006.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_sp006.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_sp006.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_trig004.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_trig004.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_row_trig004.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_trig004.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_log.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_stm_log.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_log.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_stm_log.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_crash_safe.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_stm_mixed_crash_safe.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_crash_safe.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_stm_mixed_crash_safe.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_lower_case_table_names.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_stm_mixed_lower_case_table_names.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_stm_mixed_lower_case_table_names.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_stm_mixed_lower_case_table_names.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_pk_uc0_lookup0.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_pk_uc0_lookup0.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_pk_uc0_lookup0.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_pk_uc0_lookup0.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_pk_uc0_lookup1.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_pk_uc0_lookup1.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_pk_uc0_lookup1.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_pk_uc0_lookup1.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_pk_uc1_lookup0.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_pk_uc1_lookup0.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_pk_uc1_lookup0.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_pk_uc1_lookup0.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_pk_uc1_lookup1.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_pk_uc1_lookup1.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_pk_uc1_lookup1.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_pk_uc1_lookup1.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_unique_uc0_lookup0.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_unique_uc0_lookup0.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_unique_uc0_lookup0.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_unique_uc0_lookup0.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_unique_uc0_lookup1.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_unique_uc0_lookup1.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_update_unique_uc0_lookup1.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_update_unique_uc0_lookup1.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_write_pk.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_write_pk.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_write_pk.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_write_pk.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_write_pk_uc1.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_write_pk_uc1.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_write_pk_uc1.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_write_pk_uc1.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_write_unique.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_write_unique.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_write_unique.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_write_unique.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_write_unique_uc1.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_write_unique_uc1.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_tokudb_write_unique_uc1.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_tokudb_write_unique_uc1.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_truncate_3tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_truncate_3tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_truncate_3tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_truncate_3tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/rpl_typeconv_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_typeconv_tokudb.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/rpl_typeconv_tokudb.result
rename to storage/tokudb/mysql-test/rpl/r/rpl_typeconv_tokudb.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/tokudb_innodb_xa_crash.result b/storage/tokudb/mysql-test/rpl/r/tokudb_innodb_xa_crash.result
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/r/tokudb_innodb_xa_crash.result
rename to storage/tokudb/mysql-test/rpl/r/tokudb_innodb_xa_crash.result
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/disabled.def b/storage/tokudb/mysql-test/rpl/t/disabled.def
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/disabled.def
rename to storage/tokudb/mysql-test/rpl/t/disabled.def
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_deadlock_tokudb-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_deadlock_tokudb-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_deadlock_tokudb-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_deadlock_tokudb-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_deadlock_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_deadlock_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_deadlock_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_deadlock_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_extra_col_master_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_extra_col_master_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_extra_col_master_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_extra_col_master_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_extra_col_slave_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_extra_col_slave_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_extra_col_slave_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_extra_col_slave_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_mixed_row_tokudb-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_mixed_row_tokudb-master.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_mixed_row_tokudb-master.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_mixed_row_tokudb-master.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_not_null_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_not_null_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_not_null_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_not_null_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb-master.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb-master.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb-master.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_delete_pk-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_delete_pk-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_delete_pk-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_delete_pk-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_delete_pk.test b/storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_delete_pk.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_delete_pk.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_delete_pk.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_update_pk_uc0_lookup0-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_update_pk_uc0_lookup0-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_update_pk_uc0_lookup0-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_update_pk_uc0_lookup0-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_update_pk_uc0_lookup0.test b/storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_update_pk_uc0_lookup0.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_update_pk_uc0_lookup0.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_update_pk_uc0_lookup0.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_write_pk-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_write_pk-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_write_pk-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_write_pk-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_write_pk.test b/storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_write_pk.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_parallel_tokudb_write_pk.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_parallel_tokudb_write_pk.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_partition_tokudb-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_partition_tokudb-master.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_partition_tokudb-master.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_partition_tokudb-master.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_partition_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_partition_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_partition_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_partition_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_relay_space_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_relay_space_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_relay_space_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_relay_space_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_rfr_disable_on_expl_pk_absence-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_rfr_disable_on_expl_pk_absence-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_rfr_disable_on_expl_pk_absence-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_rfr_disable_on_expl_pk_absence-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_rfr_disable_on_expl_pk_absence.test b/storage/tokudb/mysql-test/rpl/t/rpl_rfr_disable_on_expl_pk_absence.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_rfr_disable_on_expl_pk_absence.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_rfr_disable_on_expl_pk_absence.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_basic_3tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_row_basic_3tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_basic_3tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_row_basic_3tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_blob_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_row_blob_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_blob_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_row_blob_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_log_tokudb-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_row_log_tokudb-master.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_log_tokudb-master.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_row_log_tokudb-master.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_log_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_row_log_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_log_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_row_log_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_rec_comp_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_row_rec_comp_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_rec_comp_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_row_rec_comp_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_sp002_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_row_sp002_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_sp002_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_row_sp002_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_sp007_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_row_sp007_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_sp007_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_row_sp007_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_tabledefs_3tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_row_tabledefs_3tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_row_tabledefs_3tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_row_tabledefs_3tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_set_null_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_set_null_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_set_null_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_set_null_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_stm_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_stm_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_stm_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_stm_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb-master.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb-master.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb-master.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_bug28430-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_bug28430-master.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_bug28430-master.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_bug28430-master.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_bug28430-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_bug28430-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_bug28430-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_bug28430-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_bug28430.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_bug28430.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_bug28430.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_bug28430.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_bug30888.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_bug30888.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_bug30888.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_bug30888.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_commit_after_flush.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_commit_after_flush.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_commit_after_flush.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_commit_after_flush.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_delete_pk-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_delete_pk-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_delete_pk-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_delete_pk-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_delete_pk.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_delete_pk.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_delete_pk.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_delete_pk.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_delete_pk_lookup1-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_delete_pk_lookup1-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_delete_pk_lookup1-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_delete_pk_lookup1-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_delete_pk_lookup1.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_delete_pk_lookup1.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_delete_pk_lookup1.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_delete_pk_lookup1.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_insert_id-master.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-master.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_insert_id-master.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_insert_id-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_insert_id-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_insert_id.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_insert_id.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id_pk.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_insert_id_pk.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_insert_id_pk.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_insert_id_pk.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_mixed_ddl.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_mixed_ddl.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_mixed_ddl.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_mixed_ddl.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_mixed_dml.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_mixed_dml.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_mixed_dml.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_mixed_dml.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_multi_update.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_multi_update.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_multi_update2-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_multi_update2-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_multi_update2.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update2.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_multi_update2.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update3.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_multi_update3.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_multi_update3.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_multi_update3.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_ff-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_ff-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_ff.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_ff.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_ft-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_ft-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_ft.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_ft.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_tf-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_tf-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_tf.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_tf.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_tt-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_tt-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_tt.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_read_only_tt.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_rfr_partition_table-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_rfr_partition_table-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_rfr_partition_table-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_rfr_partition_table-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_rfr_partition_table.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_rfr_partition_table.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_rfr_partition_table.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_rfr_partition_table.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_crash_safe-master.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-master.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_crash_safe-master.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_crash_safe-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_crash_safe-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_crash_safe.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_crash_safe.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_crash_safe.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.cnf
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.cnf
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_blobs.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.cnf
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.cnf
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_full.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.cnf
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.cnf
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_min.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.cnf
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.cnf
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_eng_noblob.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.cnf
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.cnf
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_full.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.cnf
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.cnf
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_min.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.cnf
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.cnf
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.cnf
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_img_idx_noblob.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_log-master.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log-master.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_log-master.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_log.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_log.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_log.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_lower_case_table_names-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_lower_case_table_names-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_lower_case_table_names.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_lower_case_table_names.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_lower_case_table_names.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp003.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_sp003.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp003.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_sp003.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp006.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_sp006.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_sp006.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_sp006.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_trig004.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_trig004.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_row_trig004.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_trig004.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_log-master.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log-master.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_log-master.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_log.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_log.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_log.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_mixed_crash_safe-master.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-master.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_mixed_crash_safe-master.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_mixed_crash_safe-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_mixed_crash_safe-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_mixed_crash_safe.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_crash_safe.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_mixed_crash_safe.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_stm_mixed_lower_case_table_names.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc0_lookup0-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc0_lookup0-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc0_lookup0-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc0_lookup0-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc0_lookup0.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc0_lookup0.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc0_lookup0.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc0_lookup0.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc0_lookup1-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc0_lookup1-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc0_lookup1-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc0_lookup1-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc0_lookup1.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc0_lookup1.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc0_lookup1.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc0_lookup1.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc1_lookup0-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc1_lookup0-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc1_lookup0-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc1_lookup0-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc1_lookup0.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc1_lookup0.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc1_lookup0.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc1_lookup0.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc1_lookup1-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc1_lookup1-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc1_lookup1-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc1_lookup1-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc1_lookup1.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc1_lookup1.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_pk_uc1_lookup1.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_pk_uc1_lookup1.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_unique_uc0_lookup0-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_unique_uc0_lookup0-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_unique_uc0_lookup0-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_unique_uc0_lookup0-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_unique_uc0_lookup0.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_unique_uc0_lookup0.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_unique_uc0_lookup0.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_unique_uc0_lookup0.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_unique_uc0_lookup1-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_unique_uc0_lookup1-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_unique_uc0_lookup1-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_unique_uc0_lookup1-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_unique_uc0_lookup1.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_unique_uc0_lookup1.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_update_unique_uc0_lookup1.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_update_unique_uc0_lookup1.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_pk-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_pk-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_pk-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_pk-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_pk.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_pk.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_pk.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_pk.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_pk_uc1-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_pk_uc1-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_pk_uc1-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_pk_uc1-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_pk_uc1.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_pk_uc1.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_pk_uc1.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_pk_uc1.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_unique-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_unique-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_unique-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_unique-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_unique.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_unique.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_unique.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_unique.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_unique_uc1-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_unique_uc1-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_unique_uc1-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_unique_uc1-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_unique_uc1.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_unique_uc1.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_tokudb_write_unique_uc1.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_tokudb_write_unique_uc1.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_truncate_3tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_truncate_3tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_truncate_3tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_truncate_3tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/rpl_typeconv_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_typeconv_tokudb.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/rpl_typeconv_tokudb.test
rename to storage/tokudb/mysql-test/rpl/t/rpl_typeconv_tokudb.test
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/suite.opt b/storage/tokudb/mysql-test/rpl/t/suite.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/suite.opt
rename to storage/tokudb/mysql-test/rpl/t/suite.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/tokudb_innodb_xa_crash-slave.opt b/storage/tokudb/mysql-test/rpl/t/tokudb_innodb_xa_crash-slave.opt
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/tokudb_innodb_xa_crash-slave.opt
rename to storage/tokudb/mysql-test/rpl/t/tokudb_innodb_xa_crash-slave.opt
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/tokudb_innodb_xa_crash.test b/storage/tokudb/mysql-test/rpl/t/tokudb_innodb_xa_crash.test
similarity index 100%
rename from storage/tokudb/mysql-test/tokudb_rpl/t/tokudb_innodb_xa_crash.test
rename to storage/tokudb/mysql-test/rpl/t/tokudb_innodb_xa_crash.test
From e1aded1420d44e6f825a646df5d1aebeda8dfa64 Mon Sep 17 00:00:00 2001
From: Elena Stepanova
Date: Fri, 4 Aug 2017 02:10:19 +0300
Subject: [PATCH 098/101] Additions to 10.0.32 unstable test list after TokuDB
merge
---
mysql-test/unstable-tests | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests
index 868a6c90685..520567a0e9b 100644
--- a/mysql-test/unstable-tests
+++ b/mysql-test/unstable-tests
@@ -207,6 +207,9 @@ rpl.rpl_mdev6020 : MDEV-10630, MDEV-10417 - Timeouts, fails
rpl.rpl_parallel : MDEV-10653 - Timeouts
rpl.rpl_parallel_mdev6589 : MDEV-12979 - Assertion failure
rpl.rpl_parallel_temptable : MDEV-10356 - Crash in close_thread_tables
+rpl.rpl_parallel_tokudb_delete_pk : Opt file modified in 10.0.32
+rpl.rpl_parallel_tokudb_update_pk_uc0_lookup0 : Modified in 10.0.32
+rpl.rpl_parallel_tokudb_write_pk : Modified in 10.0.32
rpl.rpl_partition_innodb : MDEV-10417 - Fails on Mips
rpl.rpl_reset_slave_fail : Added in 10.0.32
rpl.rpl_row_basic_11bugs : MDEV-12171 - Server failed to start
@@ -215,10 +218,10 @@ rpl.rpl_row_sp001 : MDEV-9329 - Fails on Ubuntu/s390x
rpl.rpl_semi_sync : MDEV-11220 - Wrong result
rpl.rpl_semi_sync_uninstall_plugin : MDEV-7140 - Wrong plugin status
rpl.rpl_show_slave_hosts : MDEV-12171 - Server failed to start
+rpl.rpl_skip_replication : MDEV-9268 - Fails with timeout in sync_slave_with_master on Alpha
rpl.rpl_slave_grp_exec : MDEV-10514 - Unexpected deadlock
rpl.rpl_sync : MDEV-10633 - Database page corruption
rpl.rpl_temporary_error2 : MDEV-10634 - Wrong number of retries
-rpl.rpl_skip_replication : MDEV-9268 - Fails with timeout in sync_slave_with_master on Alpha
rpl/extra/rpl_tests.* : MDEV-10994 - tests not maintained
@@ -259,7 +262,9 @@ tokudb.cluster_filter_unpack_varchar : MDEV-10636 - Wrong execution plan
tokudb.dir_per_db : MDEV-11537 - wrong result
tokudb.dir_per_db_rename_to_nonexisting_schema : MDEV-12823 - Valgrind
tokudb.hotindex-update-1 : MDEV-12640 - Lost connection during query
+tokudb.kill_query_blocked_in_lt : Added in 10.0.32
tokudb.locks-select-update-1 : MDEV-13406 - Lock wait timeout
+tokudb.locks-select-update-3 : Modified in 10.0.32
tokudb.rows-32m-rand-insert : MDEV-12640 - Lost connection during query
tokudb.rows-32m-seq-insert : MDEV-12640 - Lost connection during query
@@ -272,9 +277,40 @@ tokudb_bugs.frm_store2 : MDEV-12823 - Valgrind
tokudb_bugs.frm_store3 : MDEV-12823 - Valgrind
tokudb_bugs.xa : MDEV-11804 - Lock wait timeout
+tokudb_mariadb.mdev12972 : Added in 10.0.32
+
tokudb_rpl.* : MDEV-11001 - tests don't work
tokudb_sys_vars.* : MDEV-11001 - tests don't work
+rpl-tokudb.rpl_deadlock_tokudb : Modified in 10.0.32
+rpl-tokudb.rpl_not_null_tokudb : Modified in 10.0.32
+rpl-tokudb.rpl_rfr_disable_on_expl_pk_absence : Modified in 10.0.32
+rpl-tokudb.rpl_row_basic_3tokudb : Modified in 10.0.32
+rpl-tokudb.rpl_stm_tokudb : Modified in 10.0.32
+rpl-tokudb.rpl_tokudb_commit_after_flush : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_insert_id : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_insert_id_pk : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_multi_update : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_multi_update2 : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_multi_update3 : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_rfr_partition_table : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_crash_safe : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_img_blobs : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_img_eng_full : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_img_eng_min : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_img_eng_noblob : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_img_idx_full : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_img_idx_min : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_img_idx_noblob : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_log : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_lower_case_table_names : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_sp003 : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_sp006 : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_row_trig004 : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_stm_log : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_stm_mixed_crash_safe : Added in 10.0.32
+rpl-tokudb.rpl_tokudb_stm_mixed_lower_case_table_names : Added in 10.0.32
+
#----------------------------------------------------------------
unit.ma_test_loghandler : MDEV-10638 - record read not ok
From d85d6c9c416aab85f1ded344a5b870d4cc56f9f6 Mon Sep 17 00:00:00 2001
From: Elena Stepanova
Date: Fri, 4 Aug 2017 02:11:10 +0300
Subject: [PATCH 099/101] Remove extra trailing spaces from the result file
---
storage/tokudb/mysql-test/tokudb_mariadb/r/mdev12972.result | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev12972.result b/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev12972.result
index fce77f1647d..92aefedac69 100644
--- a/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev12972.result
+++ b/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev12972.result
@@ -1,10 +1,10 @@
CREATE TABLE t1 (pk INT PRIMARY KEY, i1 INT, c1 VARCHAR(1), KEY(c1)) ENGINE=TokuDB;
-INSERT INTO t1 VALUES
+INSERT INTO t1 VALUES
(1,2,NULL),(2,5,'x'),(3,3,'i'),(4,1,'e'),(5,4,'p');
CREATE TABLE t2 (i2 INT) ENGINE=TokuDB;
INSERT INTO t2 VALUES (1),(2);
CREATE TABLE t3 (i3 INT, c3 VARCHAR(1), KEY(i3)) ENGINE=TokuDB;
-INSERT INTO t3 VALUES
+INSERT INTO t3 VALUES
(1,'e'),(1,'z'),(1,'i'),(1,'q'),(1,'i'),(1,'f'),(1,'m'),(2,'c'),(1,'d'),
(2,'n'),(1,'t'),(2,'e'),(1,'w'),(2,'y'),(1,'j'),(2,'i'),(1,'f'),(2,'f'),
(1,'s'),(2,'y');
From d2a19082c03485c69157c7b1e040f2806eb2e153 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?=
Date: Fri, 4 Aug 2017 04:27:33 +0300
Subject: [PATCH 100/101] Disable rpl_tokudb_row_img_* tests
We need to pull rpl config files from MySQL before these tests can be
run.
---
storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.cnf | 1 -
storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.test | 1 +
storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.cnf | 1 -
storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.test | 1 +
storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.cnf | 1 -
storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.test | 1 +
.../tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.cnf | 1 -
.../tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.test | 1 +
storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.cnf | 1 -
storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.test | 1 +
storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.cnf | 1 -
storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.test | 1 +
.../tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.cnf | 1 -
.../tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.test | 1 +
14 files changed, 7 insertions(+), 7 deletions(-)
delete mode 100644 storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.cnf
delete mode 100644 storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.cnf
delete mode 100644 storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.cnf
delete mode 100644 storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.cnf
delete mode 100644 storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.cnf
delete mode 100644 storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.cnf
delete mode 100644 storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.cnf
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.cnf
deleted file mode 100644
index d758d29f481..00000000000
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.cnf
+++ /dev/null
@@ -1 +0,0 @@
-!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.test
index a52e96dc19d..ff4a0435a5e 100644
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.test
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_blobs.test
@@ -1,4 +1,5 @@
#Want to skip this test from daily Valgrind execution
+skip Require rpl files from MySQL;
--source include/no_valgrind_without_big.inc
-- source include/have_innodb.inc
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.cnf
deleted file mode 100644
index d758d29f481..00000000000
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.cnf
+++ /dev/null
@@ -1 +0,0 @@
-!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.test
index cfbc6519182..68ff71752ac 100644
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.test
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_full.test
@@ -1,4 +1,5 @@
#Want to skip this test from daily Valgrind execution
+skip Require rpl files from MySQL;
-- source include/no_valgrind_without_big.inc
#
# This file contains tests for WL#5096 and bug fixes.
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.cnf
deleted file mode 100644
index d758d29f481..00000000000
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.cnf
+++ /dev/null
@@ -1 +0,0 @@
-!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.test
index 4c832208feb..3ba958fc691 100644
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.test
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_min.test
@@ -1,4 +1,5 @@
#Want to skip this test from daily Valgrind execution
+skip Require rpl files from MySQL;
-- source include/no_valgrind_without_big.inc
#
# This file contains tests for WL#5096 and bug fixes.
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.cnf
deleted file mode 100644
index d758d29f481..00000000000
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.cnf
+++ /dev/null
@@ -1 +0,0 @@
-!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.test
index 00b6448ad72..f539e3ac370 100644
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.test
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_eng_noblob.test
@@ -1,4 +1,5 @@
#Want to skip this test from daily Valgrind execution
+skip Require rpl files from MySQL;
-- source include/no_valgrind_without_big.inc
#
# This file contains tests for WL#5096 and bug fixes.
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.cnf
deleted file mode 100644
index d758d29f481..00000000000
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.cnf
+++ /dev/null
@@ -1 +0,0 @@
-!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.test
index 6f683776c3c..9dfd1675f53 100644
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.test
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_full.test
@@ -1,4 +1,5 @@
#Want to skip this test from daily Valgrind execution
+skip Require rpl files from MySQL;
-- source include/no_valgrind_without_big.inc
#
# This file contains tests for WL#5096.
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.cnf
deleted file mode 100644
index d758d29f481..00000000000
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.cnf
+++ /dev/null
@@ -1 +0,0 @@
-!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.test
index 030bc655291..03e022940a6 100644
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.test
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_min.test
@@ -1,4 +1,5 @@
#Want to skip this test from daily Valgrind execution
+skip Require rpl files from MySQL;
--source include/no_valgrind_without_big.inc
#
# This file contains tests for WL#5096.
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.cnf b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.cnf
deleted file mode 100644
index d758d29f481..00000000000
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.cnf
+++ /dev/null
@@ -1 +0,0 @@
-!include suite/rpl/t/rpl_row_img.cnf
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.test
index 785f79bccdc..ed147c8902b 100644
--- a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.test
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_row_img_idx_noblob.test
@@ -1,4 +1,5 @@
#Want to skip this test from daily Valgrind execution
+skip Require rpl files from MySQL;
-- source include/no_valgrind_without_big.inc
#
# This file contains tests for WL#5096.
From ef2e51c39637ace64b66fa82b834e31f0e4ef38a Mon Sep 17 00:00:00 2001
From: Daniel Bartholomew
Date: Mon, 7 Aug 2017 10:09:23 -0400
Subject: [PATCH 101/101] bump the VERSION
---
VERSION | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/VERSION b/VERSION
index ab62b5a1c7c..5a19a706528 100644
--- a/VERSION
+++ b/VERSION
@@ -1,3 +1,3 @@
MYSQL_VERSION_MAJOR=10
MYSQL_VERSION_MINOR=0
-MYSQL_VERSION_PATCH=32
+MYSQL_VERSION_PATCH=33