summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xBUILD/compile-dist33
-rw-r--r--configure.in66
-rw-r--r--mysql-test/extra/rpl_tests/rpl_row_basic.test99
-rw-r--r--mysql-test/r/alter_table.result12
-rw-r--r--mysql-test/r/binlog_format_basic.result3
-rw-r--r--mysql-test/r/innodb_mysql.result9
-rw-r--r--mysql-test/r/partition.result74
-rw-r--r--mysql-test/r/xa.result20
-rw-r--r--mysql-test/suite/rpl/r/rpl_redirect.result40
-rw-r--r--mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result57
-rw-r--r--mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result57
-rw-r--r--mysql-test/suite/rpl/t/disabled.def3
-rw-r--r--mysql-test/suite/rpl/t/rpl_redirect.test45
-rw-r--r--mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result57
-rw-r--r--mysql-test/t/alter_table.test12
-rw-r--r--mysql-test/t/binlog_format_basic.test7
-rw-r--r--mysql-test/t/innodb_mysql.test14
-rw-r--r--mysql-test/t/partition.test29
-rw-r--r--mysql-test/t/xa.test45
-rw-r--r--sql/field.cc35
-rw-r--r--sql/field.h2
-rw-r--r--sql/ha_partition.cc2
-rw-r--r--sql/handler.cc34
-rw-r--r--sql/log.cc2
-rw-r--r--sql/log_event.cc38
-rw-r--r--sql/log_event_old.cc47
-rw-r--r--sql/share/errmsg.txt6
-rw-r--r--sql/sql_class.cc7
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_parse.cc78
-rw-r--r--zlib/gzio.c5
31 files changed, 766 insertions, 176 deletions
diff --git a/BUILD/compile-dist b/BUILD/compile-dist
index 74690fb0c95..caee172f196 100755
--- a/BUILD/compile-dist
+++ b/BUILD/compile-dist
@@ -13,34 +13,51 @@ path=`dirname $0`
# Default to gcc for CC and CXX
if test -z "$CXX" ; then
- export CXX=gcc
+ CXX=gcc
# Set some required compile options
if test -z "$CXXFLAGS" ; then
- export CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti"
+ CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti"
fi
fi
if test -z "$CC" ; then
- export CC=gcc
+ CC=gcc
fi
# Use ccache, if available
if ccache -V > /dev/null 2>&1
then
- if ! (echo "$CC" | grep "ccache" > /dev/null)
+ if echo "$CC" | grep "ccache" > /dev/null
then
- export CC="ccache $CC"
+ :
+ else
+ CC="ccache $CC"
fi
- if ! (echo "$CXX" | grep "ccache" > /dev/null)
+ if echo "$CXX" | grep "ccache" > /dev/null
then
- export CXX="ccache $CXX"
+ :
+ else
+ CXX="ccache $CXX"
fi
fi
+if test -z "$MAKE"
+then
+ if gmake -v > /dev/null 2>&1
+ then
+ MAKE="gmake"
+ else
+ MAKE="make"
+ fi
+fi
+
+export CC CXX MAKE
+
# Make sure to enable all features that affect "make dist"
# Remember that configure restricts the man pages to the configured features !
./configure \
--with-embedded-server \
--with-ndbcluster
-make
+$MAKE
+
diff --git a/configure.in b/configure.in
index 4c98b2b6dc8..63ab547f70d 100644
--- a/configure.in
+++ b/configure.in
@@ -10,7 +10,7 @@ AC_CANONICAL_SYSTEM
#
# When changing major version number please also check switch statement
# in mysqlbinlog::check_master_version().
-AM_INIT_AUTOMAKE(mysql, 5.1.29)
+AM_INIT_AUTOMAKE(mysql, 5.1.30)
AM_CONFIG_HEADER([include/config.h:config.h.in])
PROTOCOL_VERSION=10
@@ -405,12 +405,15 @@ dnl Find paths to some shell programs
AC_PATH_PROG(LN, ln, ln)
# This must be able to take a -f flag like normal unix ln.
AC_PATH_PROG(LN_CP_F, ln, ln)
-if ! ( expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null ); then
-# If ln -f does not exists use -s (AFS systems)
-if test -n "$LN_CP_F"; then
- LN_CP_F="$LN_CP_F -s"
-fi
-fi
+case $SYSTEM_TYPE in
+ *netware*) ;;
+ *)
+ # If ln -f does not exists use -s (AFS systems)
+ if test -n "$LN_CP_F"; then
+ LN_CP_F="$LN_CP_F -s"
+ fi
+ ;;
+esac
AC_PATH_PROG(MV, mv, mv)
AC_PATH_PROG(RM, rm, rm)
@@ -1642,14 +1645,16 @@ else
OPTIMIZE_CXXFLAGS="-O"
fi
-if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null; then
- DEBUG_CFLAGS="-g -DDEBUG -sym internal,codeview4"
- DEBUG_CXXFLAGS="-g -DDEBUG -sym internal,codeview4"
- DEBUG_OPTIMIZE_CC="-DDEBUG"
- DEBUG_OPTIMIZE_CXX="-DDEBUG"
- OPTIMIZE_CFLAGS="-O3 -DNDEBUG"
- OPTIMIZE_CXXFLAGS="-O3 -DNDEBUG"
-fi
+case $SYSTEM_TYPE in
+ *netware*)
+ DEBUG_CFLAGS="-g -DDEBUG -sym internal,codeview4"
+ DEBUG_CXXFLAGS="-g -DDEBUG -sym internal,codeview4"
+ DEBUG_OPTIMIZE_CC="-DDEBUG"
+ DEBUG_OPTIMIZE_CXX="-DDEBUG"
+ OPTIMIZE_CFLAGS="-O3 -DNDEBUG"
+ OPTIMIZE_CXXFLAGS="-O3 -DNDEBUG"
+ ;;
+esac
# If the user specified CFLAGS, we won't add any optimizations
if test -n "$SAVE_CFLAGS"
@@ -1915,15 +1920,18 @@ MYSQL_TZNAME
# Do the c++ compiler have a bool type
MYSQL_CXX_BOOL
# Check some common bugs with gcc 2.8.# on sparc
-if ! ( expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null ); then
-MYSQL_CHECK_LONGLONG_TO_FLOAT
-if test "$ac_cv_conv_longlong_to_float" != "yes"
-then
- AC_MSG_ERROR([Your compiler cannot convert a longlong value to a float!
-If you are using gcc 2.8.# you should upgrade to egcs 1.0.3 or newer and try
-again])
-fi
-fi
+case $SYSTEM_TYPE in
+ *netware*) ;;
+ *)
+ MYSQL_CHECK_LONGLONG_TO_FLOAT
+ if test "$ac_cv_conv_longlong_to_float" != "yes"
+ then
+ AC_MSG_ERROR([Your compiler cannot convert a longlong value to a float!
+ If you are using gcc 2.8.# you should upgrade to egcs 1.0.3 or newer and try
+ again])
+ fi
+ ;;
+esac
AC_CHECK_TYPES([sigset_t, off_t], [], [], [#include <sys/types.h>])
AC_CHECK_TYPES([size_t], [], [], [#include <stdio.h>])
AC_CHECK_TYPES([u_int32_t])
@@ -2549,11 +2557,12 @@ readline_h_ln_cmd=""
readline_link=""
want_to_use_readline="no"
-if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null
-then
+case $SYSTEM_TYPE in
+ *netware*)
# For NetWare, do not need readline
echo "Skipping readline"
-else
+ ;;
+ *)
if [test "$with_libedit" = "yes"] || [test "$with_libedit" = "undefined"] && [test "$with_readline" = "undefined"]
then
readline_topdir="cmd-line-utils"
@@ -2606,7 +2615,8 @@ else
be built with libreadline. Please use --with-libedit to use
the bundled version of libedit instead.])
fi
-fi
+ ;;
+esac
AC_SUBST(readline_dir)
AC_SUBST(readline_topdir)
diff --git a/mysql-test/extra/rpl_tests/rpl_row_basic.test b/mysql-test/extra/rpl_tests/rpl_row_basic.test
index 7cfbcdb4437..2106ccd8a85 100644
--- a/mysql-test/extra/rpl_tests/rpl_row_basic.test
+++ b/mysql-test/extra/rpl_tests/rpl_row_basic.test
@@ -471,3 +471,102 @@ source include/diff_tables.inc;
connection master;
drop table t1;
sync_slave_with_master;
+
+#
+# BUG#40004: Replication failure with no PK + no indexes
+#
+
+# The test cases are taken from the bug report. It is difficult to
+# produce a test case that generates a HA_ERR_RECORD_DELETED, so we go
+# with the test cases we have.
+
+connection master;
+
+eval CREATE TABLE t1 (a int) ENGINE=$type;
+
+INSERT IGNORE INTO t1 VALUES (NULL);
+INSERT INTO t1 ( a ) VALUES ( 0 );
+INSERT INTO t1 ( a ) VALUES ( 9 );
+INSERT INTO t1 ( a ) VALUES ( 2 );
+INSERT INTO t1 ( a ) VALUES ( 9 );
+INSERT INTO t1 ( a ) VALUES ( 5 );
+
+UPDATE t1 SET a = 5 WHERE a = 9;
+DELETE FROM t1 WHERE a < 6;
+UPDATE t1 SET a = 9 WHERE a < 3;
+INSERT INTO t1 ( a ) VALUES ( 3 );
+UPDATE t1 SET a = 0 WHERE a < 4;
+UPDATE t1 SET a = 8 WHERE a < 5;
+
+sync_slave_with_master;
+
+let $diff_table_1=master:test.t1;
+let $diff_table_2=slave:test.t1;
+source include/diff_tables.inc;
+
+connection master;
+drop table t1;
+sync_slave_with_master;
+
+#
+# Bug #39752: Replication failure on RBR + MyISAM + no PK
+#
+
+# The test cases are taken from the bug report. It is difficult to
+# produce a test case that generates a HA_ERR_RECORD_DELETED, so we go
+# with the test cases we have.
+
+connection master;
+
+--disable_warnings
+eval CREATE TABLE t1 (a bit) ENGINE=$type;
+INSERT IGNORE INTO t1 VALUES (NULL);
+INSERT INTO t1 ( a ) VALUES ( 0 );
+UPDATE t1 SET a = 0 WHERE a = 1 LIMIT 3;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+DELETE FROM t1 WHERE a < 2 LIMIT 4;
+DELETE FROM t1 WHERE a < 9 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 9 );
+UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6;
+INSERT INTO t1 ( a ) VALUES ( 8 );
+UPDATE t1 SET a = 0 WHERE a < 6 LIMIT 0;
+INSERT INTO t1 ( a ) VALUES ( 4 );
+INSERT INTO t1 ( a ) VALUES ( 3 );
+UPDATE t1 SET a = 0 WHERE a = 7 LIMIT 6;
+DELETE FROM t1 WHERE a = 4 LIMIT 7;
+UPDATE t1 SET a = 9 WHERE a < 2 LIMIT 9;
+UPDATE t1 SET a = 0 WHERE a < 9 LIMIT 2;
+DELETE FROM t1 WHERE a < 0 LIMIT 5;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+UPDATE t1 SET a = 4 WHERE a < 6 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 8;
+DELETE FROM t1 WHERE a < 8 LIMIT 8;
+INSERT INTO t1 ( a ) VALUES ( 6 );
+DELETE FROM t1 WHERE a < 6 LIMIT 7;
+UPDATE t1 SET a = 7 WHERE a = 3 LIMIT 7;
+UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6;
+INSERT INTO t1 ( a ) VALUES ( 7 );
+DELETE FROM t1 WHERE a < 9 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 7 );
+INSERT INTO t1 ( a ) VALUES ( 6 );
+UPDATE t1 SET a = 8 WHERE a = 3 LIMIT 4;
+DELETE FROM t1 WHERE a = 2 LIMIT 9;
+DELETE FROM t1 WHERE a = 1 LIMIT 4;
+UPDATE t1 SET a = 4 WHERE a = 2 LIMIT 7;
+INSERT INTO t1 ( a ) VALUES ( 0 );
+DELETE FROM t1 WHERE a < 3 LIMIT 0;
+UPDATE t1 SET a = 8 WHERE a = 5 LIMIT 2;
+INSERT INTO t1 ( a ) VALUES ( 1 );
+UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 3;
+--enable_warnings
+
+sync_slave_with_master;
+
+let $diff_table_1=master:test.t1;
+let $diff_table_2=slave:test.t1;
+source include/diff_tables.inc;
+
+connection master;
+drop table t1;
+sync_slave_with_master;
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index d6986f4a956..c6be8f243fc 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -1222,4 +1222,16 @@ ALTER TABLE t1 CHANGE d c varchar(10);
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
DROP TABLE t1;
+CREATE TABLE t1(a INT AUTO_INCREMENT PRIMARY KEY,
+b ENUM('a', 'b', 'c') NOT NULL);
+INSERT INTO t1 (b) VALUES ('a'), ('c'), ('b'), ('b'), ('a');
+ALTER TABLE t1 MODIFY b ENUM('a', 'z', 'b', 'c') NOT NULL;
+SELECT * FROM t1;
+a b
+1 a
+2 c
+3 b
+4 b
+5 a
+DROP TABLE t1;
End of 5.1 tests
diff --git a/mysql-test/r/binlog_format_basic.result b/mysql-test/r/binlog_format_basic.result
index 3fee9bade7e..72ba35cd753 100644
--- a/mysql-test/r/binlog_format_basic.result
+++ b/mysql-test/r/binlog_format_basic.result
@@ -1,3 +1,6 @@
+SELECT @@GLOBAL.binlog_format;
+@@GLOBAL.binlog_format
+STATEMENT
'#---------------------BS_STVARS_002_01----------------------#'
SELECT COUNT(@@GLOBAL.binlog_format);
COUNT(@@GLOBAL.binlog_format)
diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result
index 985f4d2b464..2c14b1f2385 100644
--- a/mysql-test/r/innodb_mysql.result
+++ b/mysql-test/r/innodb_mysql.result
@@ -1668,3 +1668,12 @@ explain select a from t2 where a=b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL a 10 NULL # Using where; Using index
drop table t1, t2;
+SET SESSION BINLOG_FORMAT=STATEMENT;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+select @@session.sql_log_bin, @@session.binlog_format, @@session.tx_isolation;
+@@session.sql_log_bin 1
+@@session.binlog_format STATEMENT
+@@session.tx_isolation READ-COMMITTED
+CREATE TABLE t1 ( a INT ) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1);
+DROP TABLE t1;
diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result
index e76c874324e..289a24685ff 100644
--- a/mysql-test/r/partition.result
+++ b/mysql-test/r/partition.result
@@ -1,4 +1,78 @@
drop table if exists t1, t2;
+CREATE TABLE t1 (a INT NOT NULL, KEY(a))
+PARTITION BY RANGE(a)
+(PARTITION p1 VALUES LESS THAN (200), PARTITION pmax VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (2), (40), (40), (70), (60), (90), (199);
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 95 ORDER BY a ASC;
+a
+60
+70
+90
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 95;
+a
+60
+70
+90
+INSERT INTO t1 VALUES (200), (250), (210);
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 220 ORDER BY a ASC;
+a
+60
+70
+90
+199
+200
+210
+SELECT a FROM t1 WHERE a BETWEEN 200 AND 220 ORDER BY a ASC;
+a
+200
+210
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 95 ORDER BY a DESC;
+a
+90
+70
+60
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 220 ORDER BY a DESC;
+a
+210
+200
+199
+90
+70
+60
+SELECT a FROM t1 WHERE a BETWEEN 200 AND 220 ORDER BY a DESC;
+a
+210
+200
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 220;
+a
+199
+200
+210
+60
+70
+90
+SELECT a FROM t1 WHERE a BETWEEN 200 AND 220;
+a
+200
+210
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 95;
+a
+60
+70
+90
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 220;
+a
+199
+200
+210
+60
+70
+90
+SELECT a FROM t1 WHERE a BETWEEN 200 AND 220;
+a
+200
+210
+DROP TABLE t1;
CREATE TABLE t1 (
a INT NOT NULL,
b MEDIUMINT NOT NULL,
diff --git a/mysql-test/r/xa.result b/mysql-test/r/xa.result
index 5fb03d2378e..592cf07522b 100644
--- a/mysql-test/r/xa.result
+++ b/mysql-test/r/xa.result
@@ -55,3 +55,23 @@ select * from t1;
a
20
drop table t1;
+drop table if exists t1;
+create table t1(a int, b int, c varchar(20), primary key(a)) engine = innodb;
+insert into t1 values(1, 1, 'a');
+insert into t1 values(2, 2, 'b');
+xa start 'a','b';
+update t1 set c = 'aa' where a = 1;
+xa start 'a','c';
+update t1 set c = 'bb' where a = 2;
+update t1 set c = 'bb' where a = 2;
+update t1 set c = 'aa' where a = 1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select count(*) from t1;
+count(*)
+2
+xa end 'a','c';
+ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected
+xa rollback 'a','c';
+xa start 'a','c';
+drop table t1;
+End of 5.0 tests
diff --git a/mysql-test/suite/rpl/r/rpl_redirect.result b/mysql-test/suite/rpl/r/rpl_redirect.result
deleted file mode 100644
index 39a7cb3ac3b..00000000000
--- a/mysql-test/suite/rpl/r/rpl_redirect.result
+++ /dev/null
@@ -1,40 +0,0 @@
-stop slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-reset master;
-reset slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-start slave;
-SHOW SLAVE STATUS;
-SHOW SLAVE HOSTS;
-Server_id Host Port Rpl_recovery_rank Master_id
-2 127.0.0.1 SLAVE_PORT 2 1
-create table t1 ( n int);
-insert into t1 values (1),(2),(3),(4);
-insert into t1 values(5);
-SELECT * FROM t1 ORDER BY n;
-n
-1
-2
-3
-4
-5
-SELECT * FROM t1 ORDER BY n;
-n
-1
-2
-3
-4
-SELECT * FROM t1 ORDER BY n;
-n
-1
-2
-3
-4
-SELECT * FROM t1 ORDER BY n;
-n
-1
-2
-3
-4
-5
-drop table t1;
diff --git a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result
index d9d96cf7eda..76ff8e15fdb 100644
--- a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result
+++ b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result
@@ -527,3 +527,60 @@ ERROR 23000: Duplicate entry '10' for key 'PRIMARY'
INSERT INTO t1 VALUES (4);
Comparing tables master:test.t1 and slave:test.t1
drop table t1;
+CREATE TABLE t1 (a int) ENGINE='MYISAM' ;
+INSERT IGNORE INTO t1 VALUES (NULL);
+INSERT INTO t1 ( a ) VALUES ( 0 );
+INSERT INTO t1 ( a ) VALUES ( 9 );
+INSERT INTO t1 ( a ) VALUES ( 2 );
+INSERT INTO t1 ( a ) VALUES ( 9 );
+INSERT INTO t1 ( a ) VALUES ( 5 );
+UPDATE t1 SET a = 5 WHERE a = 9;
+DELETE FROM t1 WHERE a < 6;
+UPDATE t1 SET a = 9 WHERE a < 3;
+INSERT INTO t1 ( a ) VALUES ( 3 );
+UPDATE t1 SET a = 0 WHERE a < 4;
+UPDATE t1 SET a = 8 WHERE a < 5;
+Comparing tables master:test.t1 and slave:test.t1
+drop table t1;
+CREATE TABLE t1 (a bit) ENGINE='MYISAM' ;
+INSERT IGNORE INTO t1 VALUES (NULL);
+INSERT INTO t1 ( a ) VALUES ( 0 );
+UPDATE t1 SET a = 0 WHERE a = 1 LIMIT 3;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+DELETE FROM t1 WHERE a < 2 LIMIT 4;
+DELETE FROM t1 WHERE a < 9 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 9 );
+UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6;
+INSERT INTO t1 ( a ) VALUES ( 8 );
+UPDATE t1 SET a = 0 WHERE a < 6 LIMIT 0;
+INSERT INTO t1 ( a ) VALUES ( 4 );
+INSERT INTO t1 ( a ) VALUES ( 3 );
+UPDATE t1 SET a = 0 WHERE a = 7 LIMIT 6;
+DELETE FROM t1 WHERE a = 4 LIMIT 7;
+UPDATE t1 SET a = 9 WHERE a < 2 LIMIT 9;
+UPDATE t1 SET a = 0 WHERE a < 9 LIMIT 2;
+DELETE FROM t1 WHERE a < 0 LIMIT 5;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+UPDATE t1 SET a = 4 WHERE a < 6 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 8;
+DELETE FROM t1 WHERE a < 8 LIMIT 8;
+INSERT INTO t1 ( a ) VALUES ( 6 );
+DELETE FROM t1 WHERE a < 6 LIMIT 7;
+UPDATE t1 SET a = 7 WHERE a = 3 LIMIT 7;
+UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6;
+INSERT INTO t1 ( a ) VALUES ( 7 );
+DELETE FROM t1 WHERE a < 9 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 7 );
+INSERT INTO t1 ( a ) VALUES ( 6 );
+UPDATE t1 SET a = 8 WHERE a = 3 LIMIT 4;
+DELETE FROM t1 WHERE a = 2 LIMIT 9;
+DELETE FROM t1 WHERE a = 1 LIMIT 4;
+UPDATE t1 SET a = 4 WHERE a = 2 LIMIT 7;
+INSERT INTO t1 ( a ) VALUES ( 0 );
+DELETE FROM t1 WHERE a < 3 LIMIT 0;
+UPDATE t1 SET a = 8 WHERE a = 5 LIMIT 2;
+INSERT INTO t1 ( a ) VALUES ( 1 );
+UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 3;
+Comparing tables master:test.t1 and slave:test.t1
+drop table t1;
diff --git a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result
index 72c94ceb525..15673768180 100644
--- a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result
+++ b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result
@@ -527,3 +527,60 @@ ERROR 23000: Duplicate entry '10' for key 'PRIMARY'
INSERT INTO t1 VALUES (4);
Comparing tables master:test.t1 and slave:test.t1
drop table t1;
+CREATE TABLE t1 (a int) ENGINE='INNODB' ;
+INSERT IGNORE INTO t1 VALUES (NULL);
+INSERT INTO t1 ( a ) VALUES ( 0 );
+INSERT INTO t1 ( a ) VALUES ( 9 );
+INSERT INTO t1 ( a ) VALUES ( 2 );
+INSERT INTO t1 ( a ) VALUES ( 9 );
+INSERT INTO t1 ( a ) VALUES ( 5 );
+UPDATE t1 SET a = 5 WHERE a = 9;
+DELETE FROM t1 WHERE a < 6;
+UPDATE t1 SET a = 9 WHERE a < 3;
+INSERT INTO t1 ( a ) VALUES ( 3 );
+UPDATE t1 SET a = 0 WHERE a < 4;
+UPDATE t1 SET a = 8 WHERE a < 5;
+Comparing tables master:test.t1 and slave:test.t1
+drop table t1;
+CREATE TABLE t1 (a bit) ENGINE='INNODB' ;
+INSERT IGNORE INTO t1 VALUES (NULL);
+INSERT INTO t1 ( a ) VALUES ( 0 );
+UPDATE t1 SET a = 0 WHERE a = 1 LIMIT 3;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+DELETE FROM t1 WHERE a < 2 LIMIT 4;
+DELETE FROM t1 WHERE a < 9 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 9 );
+UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6;
+INSERT INTO t1 ( a ) VALUES ( 8 );
+UPDATE t1 SET a = 0 WHERE a < 6 LIMIT 0;
+INSERT INTO t1 ( a ) VALUES ( 4 );
+INSERT INTO t1 ( a ) VALUES ( 3 );
+UPDATE t1 SET a = 0 WHERE a = 7 LIMIT 6;
+DELETE FROM t1 WHERE a = 4 LIMIT 7;
+UPDATE t1 SET a = 9 WHERE a < 2 LIMIT 9;
+UPDATE t1 SET a = 0 WHERE a < 9 LIMIT 2;
+DELETE FROM t1 WHERE a < 0 LIMIT 5;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+UPDATE t1 SET a = 4 WHERE a < 6 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 8;
+DELETE FROM t1 WHERE a < 8 LIMIT 8;
+INSERT INTO t1 ( a ) VALUES ( 6 );
+DELETE FROM t1 WHERE a < 6 LIMIT 7;
+UPDATE t1 SET a = 7 WHERE a = 3 LIMIT 7;
+UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6;
+INSERT INTO t1 ( a ) VALUES ( 7 );
+DELETE FROM t1 WHERE a < 9 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 7 );
+INSERT INTO t1 ( a ) VALUES ( 6 );
+UPDATE t1 SET a = 8 WHERE a = 3 LIMIT 4;
+DELETE FROM t1 WHERE a = 2 LIMIT 9;
+DELETE FROM t1 WHERE a = 1 LIMIT 4;
+UPDATE t1 SET a = 4 WHERE a = 2 LIMIT 7;
+INSERT INTO t1 ( a ) VALUES ( 0 );
+DELETE FROM t1 WHERE a < 3 LIMIT 0;
+UPDATE t1 SET a = 8 WHERE a = 5 LIMIT 2;
+INSERT INTO t1 ( a ) VALUES ( 1 );
+UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 3;
+Comparing tables master:test.t1 and slave:test.t1
+drop table t1;
diff --git a/mysql-test/suite/rpl/t/disabled.def b/mysql-test/suite/rpl/t/disabled.def
index ebdb8014f88..8cae44a3607 100644
--- a/mysql-test/suite/rpl/t/disabled.def
+++ b/mysql-test/suite/rpl/t/disabled.def
@@ -10,6 +10,3 @@
#
##############################################################################
-rpl_redirect : Failure is sporadic and and the test is superfluous (mats)
-rpl_innodb_bug28430 : Failure on Solaris Bug #36793
-rpl_flushlog_loop : BUG#37733 2008-07-23 Sven disabled in 5.1-bugteam. the bug has been fixed in 5.1-rpl: please re-enable when that gets pushed to main
diff --git a/mysql-test/suite/rpl/t/rpl_redirect.test b/mysql-test/suite/rpl/t/rpl_redirect.test
deleted file mode 100644
index 1c6f31a030e..00000000000
--- a/mysql-test/suite/rpl/t/rpl_redirect.test
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Test of automatic redirection of queries to master/slave.
-#
-
-source include/master-slave.inc;
-# We disable this for now as PS doesn't handle redirection
---disable_ps_protocol
-
-#first, make sure the slave has had enough time to register
-save_master_pos;
-connection slave;
-sync_with_master;
-
-#discover slaves
-connection master;
-source include/show_slave_status.inc;
---replace_result $SLAVE_MYPORT SLAVE_PORT
-SHOW SLAVE HOSTS;
-rpl_probe;
-
-#turn on master/slave query direction auto-magic
-enable_rpl_parse;
-create table t1 ( n int);
-insert into t1 values (1),(2),(3),(4);
-disable_rpl_parse;
-save_master_pos;
-connection slave;
-sync_with_master;
-insert into t1 values(5);
-connection master;
-enable_rpl_parse;
-# The first of the queries will be sent to the slave, the second to the master.
-SELECT * FROM t1 ORDER BY n;
-SELECT * FROM t1 ORDER BY n;
-disable_rpl_parse;
-SELECT * FROM t1 ORDER BY n;
-connection slave;
-SELECT * FROM t1 ORDER BY n;
-
-# Cleanup
-connection master;
-drop table t1;
-sync_slave_with_master;
-
-# End of 4.1 tests
diff --git a/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result b/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result
index 2538358b4d3..ac8ca2b3bcd 100644
--- a/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result
+++ b/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result
@@ -527,3 +527,60 @@ ERROR 23000: Duplicate entry '10' for key 'PRIMARY'
INSERT INTO t1 VALUES (4);
Comparing tables master:test.t1 and slave:test.t1
drop table t1;
+CREATE TABLE t1 (a int) ENGINE='NDB' ;
+INSERT IGNORE INTO t1 VALUES (NULL);
+INSERT INTO t1 ( a ) VALUES ( 0 );
+INSERT INTO t1 ( a ) VALUES ( 9 );
+INSERT INTO t1 ( a ) VALUES ( 2 );
+INSERT INTO t1 ( a ) VALUES ( 9 );
+INSERT INTO t1 ( a ) VALUES ( 5 );
+UPDATE t1 SET a = 5 WHERE a = 9;
+DELETE FROM t1 WHERE a < 6;
+UPDATE t1 SET a = 9 WHERE a < 3;
+INSERT INTO t1 ( a ) VALUES ( 3 );
+UPDATE t1 SET a = 0 WHERE a < 4;
+UPDATE t1 SET a = 8 WHERE a < 5;
+Comparing tables master:test.t1 and slave:test.t1
+drop table t1;
+CREATE TABLE t1 (a bit) ENGINE='NDB' ;
+INSERT IGNORE INTO t1 VALUES (NULL);
+INSERT INTO t1 ( a ) VALUES ( 0 );
+UPDATE t1 SET a = 0 WHERE a = 1 LIMIT 3;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+DELETE FROM t1 WHERE a < 2 LIMIT 4;
+DELETE FROM t1 WHERE a < 9 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 9 );
+UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6;
+INSERT INTO t1 ( a ) VALUES ( 8 );
+UPDATE t1 SET a = 0 WHERE a < 6 LIMIT 0;
+INSERT INTO t1 ( a ) VALUES ( 4 );
+INSERT INTO t1 ( a ) VALUES ( 3 );
+UPDATE t1 SET a = 0 WHERE a = 7 LIMIT 6;
+DELETE FROM t1 WHERE a = 4 LIMIT 7;
+UPDATE t1 SET a = 9 WHERE a < 2 LIMIT 9;
+UPDATE t1 SET a = 0 WHERE a < 9 LIMIT 2;
+DELETE FROM t1 WHERE a < 0 LIMIT 5;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+UPDATE t1 SET a = 4 WHERE a < 6 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 5 );
+UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 8;
+DELETE FROM t1 WHERE a < 8 LIMIT 8;
+INSERT INTO t1 ( a ) VALUES ( 6 );
+DELETE FROM t1 WHERE a < 6 LIMIT 7;
+UPDATE t1 SET a = 7 WHERE a = 3 LIMIT 7;
+UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6;
+INSERT INTO t1 ( a ) VALUES ( 7 );
+DELETE FROM t1 WHERE a < 9 LIMIT 4;
+INSERT INTO t1 ( a ) VALUES ( 7 );
+INSERT INTO t1 ( a ) VALUES ( 6 );
+UPDATE t1 SET a = 8 WHERE a = 3 LIMIT 4;
+DELETE FROM t1 WHERE a = 2 LIMIT 9;
+DELETE FROM t1 WHERE a = 1 LIMIT 4;
+UPDATE t1 SET a = 4 WHERE a = 2 LIMIT 7;
+INSERT INTO t1 ( a ) VALUES ( 0 );
+DELETE FROM t1 WHERE a < 3 LIMIT 0;
+UPDATE t1 SET a = 8 WHERE a = 5 LIMIT 2;
+INSERT INTO t1 ( a ) VALUES ( 1 );
+UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 3;
+Comparing tables master:test.t1 and slave:test.t1
+drop table t1;
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index 662f9095810..c45c89095fa 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -947,4 +947,16 @@ ALTER TABLE t1 CHANGE d c varchar(10);
--disable_info
DROP TABLE t1;
+
+#
+# Bug #23113: Different behavior on altering ENUM fields between 5.0 and 5.1
+#
+CREATE TABLE t1(a INT AUTO_INCREMENT PRIMARY KEY,
+ b ENUM('a', 'b', 'c') NOT NULL);
+INSERT INTO t1 (b) VALUES ('a'), ('c'), ('b'), ('b'), ('a');
+ALTER TABLE t1 MODIFY b ENUM('a', 'z', 'b', 'c') NOT NULL;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+
--echo End of 5.1 tests
diff --git a/mysql-test/t/binlog_format_basic.test b/mysql-test/t/binlog_format_basic.test
index e9dfade8f56..819ad047c1b 100644
--- a/mysql-test/t/binlog_format_basic.test
+++ b/mysql-test/t/binlog_format_basic.test
@@ -22,6 +22,13 @@
# #
###############################################################################
+###################################################################
+# BUG#39812: Make statement replication default for 5.1 (to match 5.0)
+# We just verify that the default binlog_format is STATEMENT in 5.1.
+# In 6.0, it should be MIXED.
+###################################################################
+SELECT @@GLOBAL.binlog_format;
+
--echo '#---------------------BS_STVARS_002_01----------------------#'
####################################################################
# Displaying default value #
diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test
index bcdb1328cb7..ed8de208474 100644
--- a/mysql-test/t/innodb_mysql.test
+++ b/mysql-test/t/innodb_mysql.test
@@ -29,3 +29,17 @@ insert into t2 select @a:=A.a+10*(B.a + 10*C.a),@a, @a from t1 A, t1 B, t1 C;
explain select a from t2 where a=b;
drop table t1, t2;
+#
+# Bug #40360: Binlog related errors with binlog off
+#
+# This bug is triggered when the binlog format is STATEMENT and the
+# binary log is turned off. In this case, no error should be shown for
+# the statement since there are no replication issues.
+
+SET SESSION BINLOG_FORMAT=STATEMENT;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+query_vertical select @@session.sql_log_bin, @@session.binlog_format, @@session.tx_isolation;
+CREATE TABLE t1 ( a INT ) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1);
+DROP TABLE t1;
+
diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test
index 83e0cde8991..e016f72e75b 100644
--- a/mysql-test/t/partition.test
+++ b/mysql-test/t/partition.test
@@ -15,6 +15,35 @@ drop table if exists t1, t2;
--enable_warnings
#
+# Bug#40494: Crash MYSQL server crashes on range access with partitioning
+# and order by
+#
+CREATE TABLE t1 (a INT NOT NULL, KEY(a))
+PARTITION BY RANGE(a)
+(PARTITION p1 VALUES LESS THAN (200), PARTITION pmax VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (2), (40), (40), (70), (60), (90), (199);
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 95 ORDER BY a ASC;
+--sorted_result
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 95;
+INSERT INTO t1 VALUES (200), (250), (210);
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 220 ORDER BY a ASC;
+SELECT a FROM t1 WHERE a BETWEEN 200 AND 220 ORDER BY a ASC;
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 95 ORDER BY a DESC;
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 220 ORDER BY a DESC;
+SELECT a FROM t1 WHERE a BETWEEN 200 AND 220 ORDER BY a DESC;
+--sorted_result
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 220;
+--sorted_result
+SELECT a FROM t1 WHERE a BETWEEN 200 AND 220;
+--sorted_result
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 95;
+--sorted_result
+SELECT a FROM t1 WHERE a BETWEEN 60 AND 220;
+--sorted_result
+SELECT a FROM t1 WHERE a BETWEEN 200 AND 220;
+DROP TABLE t1;
+
+#
# Bug35931: Index search may return duplicates
#
CREATE TABLE t1 (
diff --git a/mysql-test/t/xa.test b/mysql-test/t/xa.test
index 0d564727fe3..591d7ac2c4d 100644
--- a/mysql-test/t/xa.test
+++ b/mysql-test/t/xa.test
@@ -74,3 +74,48 @@ xa start 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz';
select * from t1;
drop table t1;
+disconnect con1;
+
+#
+# Bug#28323: Server crashed in xid cache operations
+#
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1(a int, b int, c varchar(20), primary key(a)) engine = innodb;
+insert into t1 values(1, 1, 'a');
+insert into t1 values(2, 2, 'b');
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+--connection con1
+xa start 'a','b';
+update t1 set c = 'aa' where a = 1;
+--connection con2
+xa start 'a','c';
+update t1 set c = 'bb' where a = 2;
+--connection con1
+--send update t1 set c = 'bb' where a = 2
+--connection con2
+--sleep 1
+--error ER_LOCK_DEADLOCK
+update t1 set c = 'aa' where a = 1;
+select count(*) from t1;
+--error ER_XA_RBDEADLOCK
+xa end 'a','c';
+xa rollback 'a','c';
+--disconnect con2
+
+connect (con3,localhost,root,,);
+--connection con3
+xa start 'a','c';
+
+--disconnect con1
+--disconnect con3
+--connection default
+drop table t1;
+
+--echo End of 5.0 tests
diff --git a/sql/field.cc b/sql/field.cc
index 16bf0fdb070..a03beb4e8af 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -8783,28 +8783,43 @@ bool Field::eq_def(Field *field)
return 1;
}
+
/**
@return
returns 1 if the fields are equally defined
*/
+
bool Field_enum::eq_def(Field *field)
{
if (!Field::eq_def(field))
return 0;
- TYPELIB *from_lib=((Field_enum*) field)->typelib;
+ return compare_enum_values(((Field_enum*) field)->typelib);
+}
- if (typelib->count < from_lib->count)
- return 0;
- for (uint i=0 ; i < from_lib->count ; i++)
+
+bool Field_enum::compare_enum_values(TYPELIB *values)
+{
+ if (typelib->count != values->count)
+ return FALSE;
+ for (uint i= 0; i < typelib->count; i++)
if (my_strnncoll(field_charset,
- (const uchar*)typelib->type_names[i],
- strlen(typelib->type_names[i]),
- (const uchar*)from_lib->type_names[i],
- strlen(from_lib->type_names[i])))
- return 0;
- return 1;
+ (const uchar*) typelib->type_names[i],
+ typelib->type_lengths[i],
+ (const uchar*) values->type_names[i],
+ values->type_lengths[i]))
+ return FALSE;
+ return TRUE;
+}
+
+
+uint Field_enum::is_equal(Create_field *new_field)
+{
+ if (!Field_str::is_equal(new_field))
+ return 0;
+ return compare_enum_values(new_field->interval);
}
+
/**
@return
returns 1 if the fields are equally defined
diff --git a/sql/field.h b/sql/field.h
index aa69fea6bdd..81905cc64ae 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1853,6 +1853,8 @@ public:
CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
private:
int do_save_field_metadata(uchar *first_byte);
+ bool compare_enum_values(TYPELIB *values);
+ uint is_equal(Create_field *new_field);
};
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 14e321218ca..303a2c152fb 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -4084,7 +4084,7 @@ int ha_partition::read_range_next()
{
DBUG_ENTER("ha_partition::read_range_next");
- if (m_ordered)
+ if (m_ordered_scan_ongoing)
{
DBUG_RETURN(handle_ordered_next(table->record[0], eq_range));
}
diff --git a/sql/handler.cc b/sql/handler.cc
index a988c34b7ca..035a06c6f05 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1278,7 +1278,12 @@ int ha_rollback_trans(THD *thd, bool all)
trans->ha_list= 0;
trans->no_2pc=0;
if (is_real_trans)
- thd->transaction.xid_state.xid.null();
+ {
+ if (thd->transaction_rollback_request)
+ thd->transaction.xid_state.rm_error= thd->main_da.sql_errno();
+ else
+ thd->transaction.xid_state.xid.null();
+ }
if (all)
{
thd->variables.tx_isolation=thd->session_tx_isolation;
@@ -2765,7 +2770,7 @@ int handler::check_collation_compatibility()
{
ulong mysql_version= table->s->mysql_version;
- if (mysql_version < 50048)
+ if (mysql_version < 50124)
{
KEY *key= table->key_info;
KEY *key_end= key + table->s->keys;
@@ -2779,15 +2784,18 @@ int handler::check_collation_compatibility()
continue;
Field *field= table->field[key_part->fieldnr - 1];
uint cs_number= field->charset()->number;
- if (mysql_version < 50048 &&
- (cs_number == 11 || /* ascii_general_ci - bug #29499, bug #27562 */
- cs_number == 41 || /* latin7_general_ci - bug #29461 */
- cs_number == 42 || /* latin7_general_cs - bug #29461 */
- cs_number == 20 || /* latin7_estonian_cs - bug #29461 */
- cs_number == 21 || /* latin2_hungarian_ci - bug #29461 */
- cs_number == 22 || /* koi8u_general_ci - bug #29461 */
- cs_number == 23 || /* cp1251_ukrainian_ci - bug #29461 */
- cs_number == 26)) /* cp1250_general_ci - bug #29461 */
+ if ((mysql_version < 50048 &&
+ (cs_number == 11 || /* ascii_general_ci - bug #29499, bug #27562 */
+ cs_number == 41 || /* latin7_general_ci - bug #29461 */
+ cs_number == 42 || /* latin7_general_cs - bug #29461 */
+ cs_number == 20 || /* latin7_estonian_cs - bug #29461 */
+ cs_number == 21 || /* latin2_hungarian_ci - bug #29461 */
+ cs_number == 22 || /* koi8u_general_ci - bug #29461 */
+ cs_number == 23 || /* cp1251_ukrainian_ci - bug #29461 */
+ cs_number == 26)) || /* cp1250_general_ci - bug #29461 */
+ (mysql_version < 50124 &&
+ (cs_number == 33 || /* utf8_general_ci - bug #27877 */
+ cs_number == 35))) /* ucs2_general_ci - bug #27877 */
return HA_ADMIN_NEEDS_UPGRADE;
}
}
@@ -3333,8 +3341,8 @@ handler::ha_create_handler_files(const char *name, const char *old_name,
int
handler::ha_change_partitions(HA_CREATE_INFO *create_info,
const char *path,
- ulonglong *copied,
- ulonglong *deleted,
+ ulonglong * const copied,
+ ulonglong * const deleted,
const uchar *pack_frm_data,
size_t pack_frm_len)
{
diff --git a/sql/log.cc b/sql/log.cc
index 8ab2e892b27..fb8669a5731 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -3779,7 +3779,7 @@ THD::binlog_set_pending_rows_event(Rows_log_event* ev)
int
MYSQL_BIN_LOG::remove_pending_rows_event(THD *thd)
{
- DBUG_ENTER(__FUNCTION__);
+ DBUG_ENTER("MYSQL_BIN_LOG::remove_pending_rows_event");
binlog_trx_data *const trx_data=
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index f91ebf3823f..0d03593946d 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -7203,6 +7203,9 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
error= do_exec_row(rli);
+ DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
+ DBUG_ASSERT(error != HA_ERR_RECORD_DELETED);
+
table->in_use = old_thd;
switch (error)
{
@@ -7218,11 +7221,13 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
case HA_ERR_TABLE_DEF_CHANGED:
case HA_ERR_CANNOT_ADD_FOREIGN:
-
+
which are not included into to the list.
+
+ Note that HA_ERR_RECORD_DELETED is not in the list since
+ do_exec_row() should not return that error code.
*/
case HA_ERR_RECORD_CHANGED:
- case HA_ERR_RECORD_DELETED:
case HA_ERR_KEY_NOT_FOUND:
case HA_ERR_END_OF_FILE:
case HA_ERR_FOUND_DUPP_KEY:
@@ -7231,7 +7236,6 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
case HA_ERR_NO_REFERENCED_ROW:
case HA_ERR_ROW_IS_REFERENCED:
- DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1)
{
if (global_system_variables.log_warnings)
@@ -7254,7 +7258,6 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
m_curr_row_end.
*/
- DBUG_PRINT("info", ("error: %d", error));
DBUG_PRINT("info", ("curr_row: 0x%lu; curr_row_end: 0x%lu; rows_end: 0x%lu",
(ulong) m_curr_row, (ulong) m_curr_row_end, (ulong) m_rows_end));
@@ -8269,6 +8272,8 @@ Rows_log_event::write_row(const Relay_log_info *const rli,
if (error)
{
DBUG_PRINT("info",("rnd_pos() returns error %d",error));
+ if (error == HA_ERR_RECORD_DELETED)
+ error= HA_ERR_KEY_NOT_FOUND;
table->file->print_error(error, MYF(0));
DBUG_RETURN(error);
}
@@ -8301,7 +8306,9 @@ Rows_log_event::write_row(const Relay_log_info *const rli,
HA_READ_KEY_EXACT);
if (error)
{
- DBUG_PRINT("info",("index_read_idx() returns error %d",error));
+ DBUG_PRINT("info",("index_read_idx() returns %s", HA_ERR(error)));
+ if (error == HA_ERR_RECORD_DELETED)
+ error= HA_ERR_KEY_NOT_FOUND;
table->file->print_error(error, MYF(0));
DBUG_RETURN(error);
}
@@ -8574,6 +8581,8 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
if (error)
{
DBUG_PRINT("info",("rnd_pos returns error %d",error));
+ if (error == HA_ERR_RECORD_DELETED)
+ error= HA_ERR_KEY_NOT_FOUND;
table->file->print_error(error, MYF(0));
}
DBUG_RETURN(error);
@@ -8633,6 +8642,8 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
HA_READ_KEY_EXACT)))
{
DBUG_PRINT("info",("no record matching the key found in the table"));
+ if (error == HA_ERR_RECORD_DELETED)
+ error= HA_ERR_KEY_NOT_FOUND;
table->file->print_error(error, MYF(0));
table->file->ha_index_end();
goto err;
@@ -8690,8 +8701,11 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
256U - (1U << table->s->last_null_bit_pos);
}
- if ((error= table->file->index_next(table->record[0])))
+ while ((error= table->file->index_next(table->record[0])))
{
+ /* We just skip records that has already been deleted */
+ if (error == HA_ERR_RECORD_DELETED)
+ continue;
DBUG_PRINT("info",("no record matching the given row found"));
table->file->print_error(error, MYF(0));
table->file->ha_index_end();
@@ -8722,14 +8736,22 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
/* Continue until we find the right record or have made a full loop */
do
{
+ restart_rnd_next:
error= table->file->rnd_next(table->record[0]);
+ DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
switch (error) {
case 0:
- case HA_ERR_RECORD_DELETED:
break;
+ /*
+ If the record was deleted, we pick the next one without doing
+ any comparisons.
+ */
+ case HA_ERR_RECORD_DELETED:
+ goto restart_rnd_next;
+
case HA_ERR_END_OF_FILE:
if (++restart_count < 2)
table->file->ha_rnd_init(1);
@@ -8759,7 +8781,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
DBUG_DUMP("record found", table->record[0], table->s->reclength);
table->file->ha_rnd_end();
- DBUG_ASSERT(error == HA_ERR_END_OF_FILE || error == HA_ERR_RECORD_DELETED || error == 0);
+ DBUG_ASSERT(error == HA_ERR_END_OF_FILE || error == 0);
goto err;
}
ok:
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index c6b99b1bd69..75aa8722aa9 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -556,6 +556,9 @@ replace_record(THD *thd, TABLE *table,
error= table->file->rnd_pos(table->record[1], table->file->dup_ref);
if (error)
{
+ DBUG_PRINT("info",("rnd_pos() returns error %d",error));
+ if (error == HA_ERR_RECORD_DELETED)
+ error= HA_ERR_KEY_NOT_FOUND;
table->file->print_error(error, MYF(0));
DBUG_RETURN(error);
}
@@ -582,6 +585,9 @@ replace_record(THD *thd, TABLE *table,
HA_READ_KEY_EXACT);
if (error)
{
+ DBUG_PRINT("info", ("index_read_idx() returns error %d", error));
+ if (error == HA_ERR_RECORD_DELETED)
+ error= HA_ERR_KEY_NOT_FOUND;
table->file->print_error(error, MYF(0));
DBUG_RETURN(error);
}
@@ -787,11 +793,14 @@ static int find_and_fetch_row(TABLE *table, uchar *key)
256U - (1U << table->s->last_null_bit_pos);
}
- if ((error= table->file->index_next(table->record[1])))
+ while ((error= table->file->index_next(table->record[1])))
{
- table->file->print_error(error, MYF(0));
+ /* We just skip records that has already been deleted */
+ if (error == HA_ERR_RECORD_DELETED)
+ continue;
+ table->file->print_error(error, MYF(0));
table->file->ha_index_end();
- DBUG_RETURN(error);
+ DBUG_RETURN(error);
}
}
@@ -812,6 +821,7 @@ static int find_and_fetch_row(TABLE *table, uchar *key)
/* Continue until we find the right record or have made a full loop */
do
{
+ restart_rnd_next:
error= table->file->rnd_next(table->record[1]);
DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
@@ -819,8 +829,14 @@ static int find_and_fetch_row(TABLE *table, uchar *key)
switch (error) {
case 0:
+ break;
+
+ /*
+ If the record was deleted, we pick the next one without doing
+ any comparisons.
+ */
case HA_ERR_RECORD_DELETED:
- break;
+ goto restart_rnd_next;
case HA_ERR_END_OF_FILE:
if (++restart_count < 2)
@@ -1680,6 +1696,9 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli)
error= do_exec_row(rli);
+ DBUG_PRINT("info", ("error: %d", error));
+ DBUG_ASSERT(error != HA_ERR_RECORD_DELETED);
+
table->in_use = old_thd;
switch (error)
{
@@ -2100,6 +2119,8 @@ Old_rows_log_event::write_row(const Relay_log_info *const rli,
if (error)
{
DBUG_PRINT("info",("rnd_pos() returns error %d",error));
+ if (error == HA_ERR_RECORD_DELETED)
+ error= HA_ERR_KEY_NOT_FOUND;
table->file->print_error(error, MYF(0));
DBUG_RETURN(error);
}
@@ -2132,7 +2153,9 @@ Old_rows_log_event::write_row(const Relay_log_info *const rli,
HA_READ_KEY_EXACT);
if (error)
{
- DBUG_PRINT("info",("index_read_idx() returns error %d",error));
+ DBUG_PRINT("info",("index_read_idx() returns error %d", error));
+ if (error == HA_ERR_RECORD_DELETED)
+ error= HA_ERR_KEY_NOT_FOUND;
table->file->print_error(error, MYF(0));
DBUG_RETURN(error);
}
@@ -2288,6 +2311,8 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
if (error)
{
DBUG_PRINT("info",("rnd_pos returns error %d",error));
+ if (error == HA_ERR_RECORD_DELETED)
+ error= HA_ERR_KEY_NOT_FOUND;
table->file->print_error(error, MYF(0));
}
DBUG_RETURN(error);
@@ -2347,6 +2372,8 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
HA_READ_KEY_EXACT)))
{
DBUG_PRINT("info",("no record matching the key found in the table"));
+ if (error == HA_ERR_RECORD_DELETED)
+ error= HA_ERR_KEY_NOT_FOUND;
table->file->print_error(error, MYF(0));
table->file->ha_index_end();
DBUG_RETURN(error);
@@ -2404,8 +2431,11 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
256U - (1U << table->s->last_null_bit_pos);
}
- if ((error= table->file->index_next(table->record[0])))
+ while ((error= table->file->index_next(table->record[0])))
{
+ /* We just skip records that has already been deleted */
+ if (error == HA_ERR_RECORD_DELETED)
+ continue;
DBUG_PRINT("info",("no record matching the given row found"));
table->file->print_error(error, MYF(0));
table->file->ha_index_end();
@@ -2436,14 +2466,17 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
/* Continue until we find the right record or have made a full loop */
do
{
+ restart_rnd_next:
error= table->file->rnd_next(table->record[0]);
switch (error) {
case 0:
- case HA_ERR_RECORD_DELETED:
break;
+ case HA_ERR_RECORD_DELETED:
+ goto restart_rnd_next;
+
case HA_ERR_END_OF_FILE:
if (++restart_count < 2)
table->file->ha_rnd_init(1);
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 84eb5f5ba64..c6fa5366f46 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -6128,6 +6128,12 @@ ER_LOAD_DATA_INVALID_COLUMN
ER_LOG_PURGE_NO_FILE
eng "Being purged log %s was not found"
+ER_XA_RBTIMEOUT XA106
+ eng "XA_RBTIMEOUT: Transaction branch was rolled back: took too long"
+
+ER_XA_RBDEADLOCK XA102
+ eng "XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected"
+
ER_NEED_REPREPARE
eng "Prepared statement needs to be re-prepared"
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index abbb2de0a82..12b773c91d0 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2852,7 +2852,10 @@ extern "C" int thd_non_transactional_update(const MYSQL_THD thd)
extern "C" int thd_binlog_format(const MYSQL_THD thd)
{
- return (int) thd->variables.binlog_format;
+ if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG))
+ return (int) thd->variables.binlog_format;
+ else
+ return BINLOG_FORMAT_UNSPEC;
}
extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all)
@@ -3513,7 +3516,7 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans,
int THD::binlog_remove_pending_rows_event(bool clear_maps)
{
- DBUG_ENTER(__FUNCTION__);
+ DBUG_ENTER("THD::binlog_remove_pending_rows_event");
if (!mysql_bin_log.is_open())
DBUG_RETURN(0);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7696882bbcc..f5cf31d1030 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -739,7 +739,7 @@ struct st_savepoint {
Ha_trx_info *ha_list;
};
-enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED};
+enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED, XA_ROLLBACK_ONLY};
extern const char *xa_state_names[];
typedef struct st_xid_state {
@@ -747,6 +747,8 @@ typedef struct st_xid_state {
XID xid; // transaction identifier
enum xa_states xa_state; // used by external XA only
bool in_thd;
+ /* Error reported by the Resource Manager (RM) to the Transaction Manager. */
+ uint rm_error;
} XID_STATE;
extern pthread_mutex_t LOCK_xid_cache;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index b083d93a801..704c16cfdec 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -83,9 +83,57 @@ const LEX_STRING command_name[]={
};
const char *xa_state_names[]={
- "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
+ "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED", "ROLLBACK ONLY"
};
+/**
+ Mark a XA transaction as rollback-only if the RM unilaterally
+ rolled back the transaction branch.
+
+ @note If a rollback was requested by the RM, this function sets
+ the appropriate rollback error code and transits the state
+ to XA_ROLLBACK_ONLY.
+
+ @return TRUE if transaction was rolled back or if the transaction
+ state is XA_ROLLBACK_ONLY. FALSE otherwise.
+*/
+static bool xa_trans_rolled_back(XID_STATE *xid_state)
+{
+ if (xid_state->rm_error)
+ {
+ switch (xid_state->rm_error) {
+ case ER_LOCK_WAIT_TIMEOUT:
+ my_error(ER_XA_RBTIMEOUT, MYF(0));
+ break;
+ case ER_LOCK_DEADLOCK:
+ my_error(ER_XA_RBDEADLOCK, MYF(0));
+ break;
+ default:
+ my_error(ER_XA_RBROLLBACK, MYF(0));
+ }
+ xid_state->xa_state= XA_ROLLBACK_ONLY;
+ }
+
+ return (xid_state->xa_state == XA_ROLLBACK_ONLY);
+}
+
+/**
+ Rollback work done on behalf of at ransaction branch.
+*/
+static bool xa_trans_rollback(THD *thd)
+{
+ bool status= test(ha_rollback(thd));
+
+ thd->options&= ~(ulong) OPTION_BEGIN;
+ thd->transaction.all.modified_non_trans_table= FALSE;
+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ xid_cache_delete(&thd->transaction.xid_state);
+ thd->transaction.xid_state.xa_state= XA_NOTR;
+ thd->transaction.xid_state.rm_error= 0;
+
+ return status;
+}
+
static void unlock_locked_tables(THD *thd)
{
if (thd->locked_tables)
@@ -4505,6 +4553,7 @@ create_sp_error:
}
DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
thd->transaction.xid_state.xa_state=XA_ACTIVE;
+ thd->transaction.xid_state.rm_error= 0;
thd->transaction.xid_state.xid.set(thd->lex->xid);
xid_cache_insert(&thd->transaction.xid_state);
thd->transaction.all.modified_non_trans_table= FALSE;
@@ -4530,6 +4579,8 @@ create_sp_error:
my_error(ER_XAER_NOTA, MYF(0));
break;
}
+ if (xa_trans_rolled_back(&thd->transaction.xid_state))
+ break;
thd->transaction.xid_state.xa_state=XA_IDLE;
my_ok(thd);
break;
@@ -4561,6 +4612,12 @@ create_sp_error:
XID_STATE *xs=xid_cache_search(thd->lex->xid);
if (!xs || xs->in_thd)
my_error(ER_XAER_NOTA, MYF(0));
+ else if (xa_trans_rolled_back(xs))
+ {
+ ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
+ xid_cache_delete(xs);
+ break;
+ }
else
{
ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
@@ -4569,6 +4626,11 @@ create_sp_error:
}
break;
}
+ if (xa_trans_rolled_back(&thd->transaction.xid_state))
+ {
+ xa_trans_rollback(thd);
+ break;
+ }
if (thd->transaction.xid_state.xa_state == XA_IDLE &&
thd->lex->xa_opt == XA_ONE_PHASE)
{
@@ -4615,28 +4677,26 @@ create_sp_error:
my_error(ER_XAER_NOTA, MYF(0));
else
{
+ bool ok= !xa_trans_rolled_back(xs);
ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
xid_cache_delete(xs);
- my_ok(thd);
+ if (ok)
+ my_ok(thd);
}
break;
}
if (thd->transaction.xid_state.xa_state != XA_IDLE &&
- thd->transaction.xid_state.xa_state != XA_PREPARED)
+ thd->transaction.xid_state.xa_state != XA_PREPARED &&
+ thd->transaction.xid_state.xa_state != XA_ROLLBACK_ONLY)
{
my_error(ER_XAER_RMFAIL, MYF(0),
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
- if (ha_rollback(thd))
+ if (xa_trans_rollback(thd))
my_error(ER_XAER_RMERR, MYF(0));
else
my_ok(thd);
- thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
- thd->transaction.all.modified_non_trans_table= FALSE;
- thd->server_status&= ~SERVER_STATUS_IN_TRANS;
- xid_cache_delete(&thd->transaction.xid_state);
- thd->transaction.xid_state.xa_state=XA_NOTR;
break;
case SQLCOM_XA_RECOVER:
res= mysql_xa_recover(thd);
diff --git a/zlib/gzio.c b/zlib/gzio.c
index 7e90f4928fc..ed4e77ca7e9 100644
--- a/zlib/gzio.c
+++ b/zlib/gzio.c
@@ -7,6 +7,11 @@
/* @(#) $Id$ */
+/* Need to be included "early" to control other headers */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdio.h>
#include "zutil.h"