summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/binlog/r/binlog_stm_ps.result3
-rw-r--r--mysql-test/suite/binlog/r/binlog_unsafe.result28
-rw-r--r--mysql-test/suite/binlog/t/binlog_unsafe.test22
-rw-r--r--sql/sql_delete.cc13
-rw-r--r--sql/sql_insert.cc13
-rw-r--r--sql/sql_update.cc13
6 files changed, 90 insertions, 2 deletions
diff --git a/mysql-test/suite/binlog/r/binlog_stm_ps.result b/mysql-test/suite/binlog/r/binlog_stm_ps.result
index 47934665116..2128367deb5 100644
--- a/mysql-test/suite/binlog/r/binlog_stm_ps.result
+++ b/mysql-test/suite/binlog/r/binlog_stm_ps.result
@@ -16,5 +16,6 @@ master-bin.000001 # Query # # use `test`; create table t1 (a int)
master-bin.000001 # User var # # @`a`=98
master-bin.000001 # Query # # use `test`; insert into t1 values (@a),(98)
master-bin.000001 # Query # # use `test`; insert into t1 values (99)
-master-bin.000001 # Query # # use `test`; insert into t1 select 100 limit 100
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
drop table t1;
diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result
index 47284ed8bc3..9d7f359ef15 100644
--- a/mysql-test/suite/binlog/r/binlog_unsafe.result
+++ b/mysql-test/suite/binlog/r/binlog_unsafe.result
@@ -11,3 +11,31 @@ Level Warning
Code 1592
Message Statement is not safe to log in statement format.
DROP TABLE t1,t2,t3;
+CREATE TABLE t1(a INT, b INT, KEY(a), PRIMARY KEY(b));
+INSERT INTO t1 SELECT * FROM t1 LIMIT 1;
+Warnings:
+Warning 1592 Statement is not safe to log in statement format.
+REPLACE INTO t1 SELECT * FROM t1 LIMIT 1;
+Warnings:
+Warning 1592 Statement is not safe to log in statement format.
+UPDATE t1 SET a=1 LIMIT 1;
+Warnings:
+Warning 1592 Statement is not safe to log in statement format.
+DELETE FROM t1 LIMIT 1;
+Warnings:
+Warning 1592 Statement is not safe to log in statement format.
+CREATE PROCEDURE p1()
+BEGIN
+INSERT INTO t1 SELECT * FROM t1 LIMIT 1;
+REPLACE INTO t1 SELECT * FROM t1 LIMIT 1;
+UPDATE t1 SET a=1 LIMIT 1;
+DELETE FROM t1 LIMIT 1;
+END|
+CALL p1();
+Warnings:
+Warning 1592 Statement is not safe to log in statement format.
+Warning 1592 Statement is not safe to log in statement format.
+Warning 1592 Statement is not safe to log in statement format.
+Warning 1592 Statement is not safe to log in statement format.
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test
index f34c22dc5f7..de15f5f6f14 100644
--- a/mysql-test/suite/binlog/t/binlog_unsafe.test
+++ b/mysql-test/suite/binlog/t/binlog_unsafe.test
@@ -15,4 +15,24 @@ query_vertical SHOW WARNINGS;
DROP TABLE t1,t2,t3;
-
+#
+# BUG#34768 - nondeterministic INSERT using LIMIT logged in stmt mode if
+# binlog_format=mixed
+#
+CREATE TABLE t1(a INT, b INT, KEY(a), PRIMARY KEY(b));
+INSERT INTO t1 SELECT * FROM t1 LIMIT 1;
+REPLACE INTO t1 SELECT * FROM t1 LIMIT 1;
+UPDATE t1 SET a=1 LIMIT 1;
+DELETE FROM t1 LIMIT 1;
+delimiter |;
+CREATE PROCEDURE p1()
+BEGIN
+ INSERT INTO t1 SELECT * FROM t1 LIMIT 1;
+ REPLACE INTO t1 SELECT * FROM t1 LIMIT 1;
+ UPDATE t1 SET a=1 LIMIT 1;
+ DELETE FROM t1 LIMIT 1;
+END|
+delimiter ;|
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 990f7713561..abf25e96be0 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -418,6 +418,19 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
DBUG_ENTER("mysql_prepare_delete");
List<Item> all_fields;
+ /*
+ Statement-based replication of DELETE ... LIMIT is not safe as order of
+ rows is not defined, so in mixed mode we go to row-based.
+
+ Note that we may consider a statement as safe if ORDER BY primary_key
+ is present. However it may confuse users to see very similiar statements
+ replicated differently.
+ */
+ if (thd->lex->current_select->select_limit)
+ {
+ thd->lex->set_stmt_unsafe();
+ thd->set_current_stmt_binlog_row_based_if_mixed();
+ }
thd->lex->allow_sum_func= 0;
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list,
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 2be932a6040..58acf40964b 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2764,6 +2764,19 @@ bool mysql_insert_select_prepare(THD *thd)
DBUG_ENTER("mysql_insert_select_prepare");
/*
+ Statement-based replication of INSERT ... SELECT ... LIMIT is not safe
+ as order of rows is not defined, so in mixed mode we go to row-based.
+
+ Note that we may consider a statement as safe if ORDER BY primary_key
+ is present or we SELECT a constant. However it may confuse users to
+ see very similiar statements replicated differently.
+ */
+ if (lex->current_select->select_limit)
+ {
+ lex->set_stmt_unsafe();
+ thd->set_current_stmt_binlog_row_based_if_mixed();
+ }
+ /*
SELECT_LEX do not belong to INSERT statement, so we can't add WHERE
clause if table is VIEW
*/
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 7c9ead7591c..77d5fd7421c 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -859,6 +859,19 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_update");
+ /*
+ Statement-based replication of UPDATE ... LIMIT is not safe as order of
+ rows is not defined, so in mixed mode we go to row-based.
+
+ Note that we may consider a statement as safe if ORDER BY primary_key
+ is present. However it may confuse users to see very similiar statements
+ replicated differently.
+ */
+ if (thd->lex->current_select->select_limit)
+ {
+ thd->lex->set_stmt_unsafe();
+ thd->set_current_stmt_binlog_row_based_if_mixed();
+ }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table_list->grant.want_privilege= table->grant.want_privilege=
(SELECT_ACL & ~table->grant.privilege);