mirror of
https://github.com/MariaDB/server.git
synced 2025-02-01 19:41:47 +01:00
f404c96e82
This is a post-push fix addressing review requests and problems with extra warnings. Problem 1: The sub-statement where an unsafe warning was detected was printed as part of the warning. This was ok for statements that were unsafe due to, e.g., calls to UUID(), but did not make sense for statements that were unsafe because there was more than one autoincrement column (unsafeness in this case comes from the combination of several sub-statements). Fix 1: Instead of printing the sub-statement, print an explanation of why the statement is unsafe. Problem 2: When a recursive construct (i.e., stored proceure, stored function, trigger, view, prepared statement) contained several sub-statements, and at least one of them was unsafe, there would be one unsafeness warning per sub-statement - even for safe sub-statements. Fix 2: Ensure that each type of warning is printed at most once, by remembering throughout the execution of the statement which types of warnings have been printed. mysql-test/extra/rpl_tests/create_recursive_construct.inc: - Clarified comment per review request. - Added checks for the number of warnings in each invocation. mysql-test/extra/rpl_tests/rpl_insert_delayed.test: Per review request, replaced @@session.binlog_format by @@global.binlog_format, since INSERT DELAYED reads the global variable. (In this test case, the two variables have the same value, so the change is cosmetic.) mysql-test/r/sp_trans.result: updated result file mysql-test/suite/binlog/r/binlog_statement_insert_delayed.result: updated result file mysql-test/suite/binlog/r/binlog_stm_ps.result: updated result file mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result: updated result file mysql-test/suite/binlog/r/binlog_unsafe.result: Updated result file. Note that duplicate warnings are now gone. mysql-test/suite/binlog/t/binlog_unsafe.test: - Added tests for: (1) a statement that is unsafe in many ways; (2) a statement that is unsafe in the same way several times. - Use -- style to invoke mysqltest commands. mysql-test/suite/rpl/r/rpl_stm_found_rows.result: updated result file mysql-test/suite/rpl/r/rpl_stm_loadfile.result: updated result file mysql-test/suite/rpl/t/rpl_mix_found_rows.test: Per review request, added comment explaining what the test case does (copied from rpl_stm_found_rows.test) mysql-test/suite/rpl/t/rpl_stm_found_rows.test: Clarified grammar in comment. mysql-test/suite/rpl_ndb/r/rpl_ndb_binlog_format_errors.result: Updated result file. sql/item_create.cc: Made set_stmt_unsafe take one parameter, describing the type of unsafeness. sql/sp_head.cc: Added unsafe_flags field and made it hold all the unsafe flags. sql/sp_head.h: - Removed the BINLOG_ROW_BASED_IF_MIXED flag from m_flags. Instead, we use the new unsafe_flags field to hold the unsafeness state of the sp. - Made propagate_attributes() copy all unsafe flags. sql/sql_base.cc: - Made LEX::set_stmt_unsafe() take an extra argument. - Made binlog_unsafe_warning_flags store the type of unsafeness. - Per review requests, clarified comments - Added DBUG printouts sql/sql_class.cc: - Made warnings be generated in issue_warnings() and call that from binlog_query(). Wrote issue_warnings(), which prints zero or more warnings, avoiding to print warnings more than once per statement. - Per review request, added @todo so that we remember to assert correct behavior in binlog_query. sql/sql_class.h: - Removed BINLOG_WARNING_PRINTED - Use [set|clear]_current_stmt_binlog_row_based() instead of modifying the flag directly. - added issue_unsafe_warnings() (only called from binlog_unsafe) - Per review request, improved some documentation. sql/sql_insert.cc: Added extra argument to LEX::set_stmt_unsafe() sql/sql_lex.h: - Added enum_binlog_stmt_unsafe, listing all types of unsafe statements. - Per review requests, improved many comments for member functions. - Added [get|set]_stmt_unsafe_flags(), which return/set all the unsafe flags for a statement. sql/sql_parse.cc: - Renamed binlog_warning_flags to binlog_unsafe_warning_flags. - Per review requests, improved comment. sql/sql_view.cc: Made views propagate all the new unsafe flags. sql/sql_yacc.yy: Added parameter to set_stmt_unsafe(). storage/innobase/handler/ha_innodb.cc: Per review requests, replaced DBUG_EXECUTE_IF() by DBUG_EVALUATE_IF().
158 lines
4 KiB
Text
158 lines
4 KiB
Text
source include/master-slave.inc;
|
|
source include/have_binlog_format_mixed.inc;
|
|
|
|
# It is not possible to replicate FOUND_ROWS() using statement-based
|
|
# replication, but there is a workaround that stores the result of
|
|
# FOUND_ROWS() into a user variable and then replicates this instead.
|
|
#
|
|
# The purpose of this test case is to test that the workaround works
|
|
# properly even when inside stored programs (i.e., stored routines and
|
|
# triggers).
|
|
|
|
--echo ==== Initialize ====
|
|
|
|
--echo **** On Master ****
|
|
connection master;
|
|
CREATE TABLE t1 (a INT);
|
|
CREATE TABLE logtbl (sect INT, test INT, count INT);
|
|
|
|
INSERT INTO t1 VALUES (1),(2),(3);
|
|
INSERT INTO t1 SELECT 2*a+3 FROM t1;
|
|
INSERT INTO t1 SELECT 2*a+3 FROM t1;
|
|
INSERT INTO t1 SELECT 2*a+3 FROM t1;
|
|
INSERT INTO t1 SELECT 2*a+3 FROM t1;
|
|
INSERT INTO t1 SELECT 2*a+3 FROM t1;
|
|
INSERT INTO t1 SELECT 2*a+3 FROM t1;
|
|
|
|
--echo ==== Checking a procedure ====
|
|
|
|
--echo **** On Master ****
|
|
connection master;
|
|
|
|
# We will now check some stuff that will not work in statement-based
|
|
# replication, but which should cause the binary log to switch to
|
|
# row-based logging.
|
|
|
|
--delimiter $$
|
|
CREATE PROCEDURE just_log(sect INT, test INT) BEGIN
|
|
INSERT INTO logtbl VALUES (sect,test,FOUND_ROWS());
|
|
END $$
|
|
--delimiter ;
|
|
sync_slave_with_master;
|
|
|
|
--echo **** On Master 1 ****
|
|
connection master1;
|
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
|
|
CALL just_log(1,1);
|
|
|
|
--echo **** On Master ****
|
|
connection master;
|
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
|
|
CALL just_log(1,2);
|
|
|
|
--echo **** On Master 1 ****
|
|
|
|
connection master1;
|
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
|
|
CALL just_log(1,3);
|
|
sync_slave_with_master;
|
|
|
|
--echo **** On Master ****
|
|
connection master;
|
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
|
|
CALL just_log(1,4);
|
|
sync_slave_with_master;
|
|
|
|
connection master;
|
|
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
|
|
--echo **** On Slave ****
|
|
sync_slave_with_master;
|
|
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
|
|
|
|
--echo ==== Checking a stored function ====
|
|
--echo **** On Master ****
|
|
connection master;
|
|
--delimiter $$
|
|
CREATE FUNCTION log_rows(sect INT, test INT)
|
|
RETURNS INT
|
|
BEGIN
|
|
DECLARE found_rows INT;
|
|
SELECT FOUND_ROWS() INTO found_rows;
|
|
INSERT INTO logtbl VALUES(sect,test,found_rows);
|
|
RETURN found_rows;
|
|
END $$
|
|
--delimiter ;
|
|
|
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
|
|
SELECT log_rows(2,1), log_rows(2,2);
|
|
|
|
CREATE TABLE t2 (a INT, b INT);
|
|
|
|
# Trying with referencing FOUND_ROWS() directly in the trigger.
|
|
|
|
--delimiter $$
|
|
CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
|
|
BEGIN
|
|
INSERT INTO logtbl VALUES (NEW.a, NEW.b, FOUND_ROWS());
|
|
END $$
|
|
--delimiter ;
|
|
|
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
|
|
INSERT INTO t2 VALUES (2,3), (2,4);
|
|
|
|
# Referencing FOUND_ROWS() indirectly.
|
|
|
|
DROP TRIGGER t2_tr;
|
|
|
|
--delimiter $$
|
|
CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
|
|
BEGIN
|
|
DECLARE dummy INT;
|
|
SELECT log_rows(NEW.a, NEW.b) INTO dummy;
|
|
END $$
|
|
--delimiter ;
|
|
|
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
|
|
INSERT INTO t2 VALUES (2,5), (2,6);
|
|
|
|
# Putting FOUND_ROWS() even lower in the call chain.
|
|
|
|
connection master;
|
|
DROP TRIGGER t2_tr;
|
|
|
|
--delimiter $$
|
|
CREATE PROCEDURE log_me_inner(sect INT, test INT)
|
|
BEGIN
|
|
DECLARE dummy INT;
|
|
SELECT log_rows(sect, test) INTO dummy;
|
|
SELECT log_rows(sect, test+1) INTO dummy;
|
|
END $$
|
|
|
|
CREATE PROCEDURE log_me(sect INT, test INT)
|
|
BEGIN
|
|
CALL log_me_inner(sect,test);
|
|
END $$
|
|
--delimiter ;
|
|
|
|
--delimiter $$
|
|
CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
|
|
BEGIN
|
|
CALL log_me(NEW.a, NEW.b);
|
|
END $$
|
|
--delimiter ;
|
|
|
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
|
|
INSERT INTO t2 VALUES (2,5), (2,6);
|
|
|
|
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
|
|
sync_slave_with_master;
|
|
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
|
|
|
|
connection master;
|
|
DROP TABLE t1, t2, logtbl;
|
|
DROP PROCEDURE just_log;
|
|
DROP PROCEDURE log_me;
|
|
DROP PROCEDURE log_me_inner;
|
|
DROP FUNCTION log_rows;
|
|
sync_slave_with_master;
|
|
|