mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
BUG#47995: Mark system functions as unsafe
Problem: Some system functions that could return different values on master and slave were not marked unsafe. In particular: GET_LOCK IS_FREE_LOCK IS_USED_LOCK MASTER_POS_WAIT RELEASE_LOCK SLEEP SYSDATE VERSION Fix: Mark these functions unsafe. mysql-test/extra/rpl_tests/rpl_stm_000001.test: - The test does not work in mixed mode any more, since it tries to simulate an error in the sql thread in a query that uses get_lock. Since get_lock now causes the query to be logged in row format, the error didn't happen. Hence, we now force statement mode. - Warnings must be disabled when the unsafe query is issued. - Replaced some save_master_pos+connection slave+sync_with_master by sync_slave_with_master. mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result: updated result file mysql-test/suite/binlog/r/binlog_stm_row.result: updated result file mysql-test/suite/binlog/r/binlog_unsafe.result: updated result file mysql-test/suite/binlog/t/binlog_killed.test: binlog_killed only works in statement format now, since it switches to row mode in mixed mode. mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test: suppress warnings for unsafe statements mysql-test/suite/binlog/t/binlog_stm_row.test: - Suppress warnings in test that causes warnings. - The test sets binlog format explicitly, so no need to execute it twice. mysql-test/suite/binlog/t/binlog_unsafe.test: Added test for all unsafe system functions. This test also includes system functions that were unsafe prior to BUG#47995. mysql-test/suite/rpl/r/rpl_err_ignoredtable.result: updated result file mysql-test/suite/rpl/r/rpl_get_lock.result: updated result file mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result: new result file mysql-test/suite/rpl/r/rpl_stm_000001.result: updated result file mysql-test/suite/rpl/r/rpl_trigger.result: updated result file mysql-test/suite/rpl/t/rpl_err_ignoredtable.test: - suppress warnings for unsafe statement - replaced save_master_pos+connection slave+sync_with_master with sync_slave_with_master mysql-test/suite/rpl/t/rpl_get_lock.test: update test case that causes new warnings mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test: Added new test case for nondeterministic functions. mysql-test/suite/rpl/t/rpl_trigger.test: update test case that causes new warnings sql/item_create.cc: Marked some system functions unsafe. sql/item_strfunc.cc: Clarified comment related to this bug. sql/sql_yacc.yy: Marked sysdate unsafe.
This commit is contained in:
@ -1,6 +1,11 @@
|
|||||||
-- source include/have_binlog_format_mixed_or_statement.inc
|
# Requires binlog_format=statement format since query involving
|
||||||
|
# get_lock() is logged in row format if binlog_format=mixed or row.
|
||||||
|
-- source include/have_binlog_format_statement.inc
|
||||||
-- source include/master-slave.inc
|
-- source include/master-slave.inc
|
||||||
|
|
||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
|
|
||||||
|
# Load some data into t1
|
||||||
create table t1 (word char(20) not null);
|
create table t1 (word char(20) not null);
|
||||||
load data infile '../../std_data/words.dat' into table t1;
|
load data infile '../../std_data/words.dat' into table t1;
|
||||||
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
|
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
|
||||||
@ -10,9 +15,7 @@ select * from t1 limit 10;
|
|||||||
#
|
#
|
||||||
# Test slave with wrong password
|
# Test slave with wrong password
|
||||||
#
|
#
|
||||||
save_master_pos;
|
sync_slave_with_master;
|
||||||
connection slave;
|
|
||||||
sync_with_master;
|
|
||||||
stop slave;
|
stop slave;
|
||||||
connection master;
|
connection master;
|
||||||
set password for root@"localhost" = password('foo');
|
set password for root@"localhost" = password('foo');
|
||||||
@ -29,16 +32,12 @@ sleep 2;
|
|||||||
|
|
||||||
create table t3(n int);
|
create table t3(n int);
|
||||||
insert into t3 values(1),(2);
|
insert into t3 values(1),(2);
|
||||||
save_master_pos;
|
sync_slave_with_master;
|
||||||
connection slave;
|
|
||||||
sync_with_master;
|
|
||||||
select * from t3;
|
select * from t3;
|
||||||
select sum(length(word)) from t1;
|
select sum(length(word)) from t1;
|
||||||
connection master;
|
connection master;
|
||||||
drop table t1,t3;
|
drop table t1,t3;
|
||||||
save_master_pos;
|
sync_slave_with_master;
|
||||||
connection slave;
|
|
||||||
sync_with_master;
|
|
||||||
|
|
||||||
# Test if the slave SQL thread can be more than 16K behind the slave
|
# Test if the slave SQL thread can be more than 16K behind the slave
|
||||||
# I/O thread (> IO_SIZE)
|
# I/O thread (> IO_SIZE)
|
||||||
@ -77,12 +76,13 @@ unlock tables;
|
|||||||
connection master;
|
connection master;
|
||||||
create table t2(id int);
|
create table t2(id int);
|
||||||
insert into t2 values(connection_id());
|
insert into t2 values(connection_id());
|
||||||
save_master_pos;
|
|
||||||
|
|
||||||
connection master1;
|
connection master1;
|
||||||
# Avoid generating result
|
# Avoid generating result
|
||||||
create temporary table t3(n int);
|
create temporary table t3(n int);
|
||||||
|
--disable_warnings
|
||||||
insert into t3 select get_lock('crash_lock%20C', 1) from t2;
|
insert into t3 select get_lock('crash_lock%20C', 1) from t2;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
connection master;
|
connection master;
|
||||||
send update t1 set n = n + get_lock('crash_lock%20C', 2);
|
send update t1 set n = n + get_lock('crash_lock%20C', 2);
|
||||||
@ -93,8 +93,11 @@ kill @id;
|
|||||||
# We don't drop t3 as this is a temporary table
|
# We don't drop t3 as this is a temporary table
|
||||||
drop table t2;
|
drop table t2;
|
||||||
connection master;
|
connection master;
|
||||||
|
# The get_lock function causes warning for unsafe statement.
|
||||||
|
--disable_warnings
|
||||||
--error 1317,2013
|
--error 1317,2013
|
||||||
reap;
|
reap;
|
||||||
|
--enable_warnings
|
||||||
connection slave;
|
connection slave;
|
||||||
# The SQL slave thread should now have stopped because the query was killed on
|
# The SQL slave thread should now have stopped because the query was killed on
|
||||||
# the master (so it has a non-zero error code in the binlog).
|
# the master (so it has a non-zero error code in the binlog).
|
||||||
@ -117,16 +120,12 @@ insert into mysql.user (Host, User, Password)
|
|||||||
select select_priv,user from mysql.user where user = _binary'blafasel2';
|
select select_priv,user from mysql.user where user = _binary'blafasel2';
|
||||||
update mysql.user set Select_priv = "Y" where User= _binary"blafasel2";
|
update mysql.user set Select_priv = "Y" where User= _binary"blafasel2";
|
||||||
select select_priv,user from mysql.user where user = _binary'blafasel2';
|
select select_priv,user from mysql.user where user = _binary'blafasel2';
|
||||||
save_master_pos;
|
sync_slave_with_master;
|
||||||
connection slave;
|
|
||||||
sync_with_master;
|
|
||||||
select n from t1;
|
select n from t1;
|
||||||
select select_priv,user from mysql.user where user = _binary'blafasel2';
|
select select_priv,user from mysql.user where user = _binary'blafasel2';
|
||||||
connection master1;
|
connection master1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
delete from mysql.user where user="blafasel2";
|
delete from mysql.user where user="blafasel2";
|
||||||
save_master_pos;
|
sync_slave_with_master;
|
||||||
connection slave;
|
|
||||||
sync_with_master;
|
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
drop table if exists t1, t2;
|
drop table if exists t1, t2;
|
||||||
create table t1 (a int) engine=innodb;
|
create table t1 (a int) engine=innodb;
|
||||||
create table t2 (a int) engine=myisam;
|
create table t2 (a int) engine=myisam;
|
||||||
@ -224,6 +225,8 @@ create table t0 (n int);
|
|||||||
insert t0 select * from t1;
|
insert t0 select * from t1;
|
||||||
set autocommit=1;
|
set autocommit=1;
|
||||||
insert into t0 select GET_LOCK("lock1",null);
|
insert into t0 select GET_LOCK("lock1",null);
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
set autocommit=0;
|
set autocommit=0;
|
||||||
create table t2 (n int) engine=innodb;
|
create table t2 (n int) engine=innodb;
|
||||||
insert into t2 values (3);
|
insert into t2 values (3);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
DROP TABLE IF EXISTS t2;
|
DROP TABLE IF EXISTS t2;
|
||||||
set @saved_global_binlog_format = @@global.binlog_format;
|
set @saved_global_binlog_format = @@global.binlog_format;
|
||||||
@ -29,6 +30,8 @@ SELECT RELEASE_LOCK('Bug#34306');
|
|||||||
RELEASE_LOCK('Bug#34306')
|
RELEASE_LOCK('Bug#34306')
|
||||||
1
|
1
|
||||||
# con2
|
# con2
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
SELECT RELEASE_LOCK('Bug#34306');
|
SELECT RELEASE_LOCK('Bug#34306');
|
||||||
RELEASE_LOCK('Bug#34306')
|
RELEASE_LOCK('Bug#34306')
|
||||||
1
|
1
|
||||||
|
@ -327,4 +327,86 @@ Warnings:
|
|||||||
Note 1592 Statement may not be safe to log in statement format.
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
SET @@SESSION.SQL_MODE = @save_sql_mode;
|
SET @@SESSION.SQL_MODE = @save_sql_mode;
|
||||||
|
CREATE TABLE t1 (a VARCHAR(1000));
|
||||||
|
INSERT INTO t1 VALUES (CURRENT_USER());
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (FOUND_ROWS());
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (GET_LOCK('tmp', 1));
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (IS_FREE_LOCK('tmp'));
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (IS_USED_LOCK('tmp'));
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (LOAD_FILE('../../std_data/words2.dat'));
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (MASTER_POS_WAIT('dummy arg', 4711, 1));
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (RELEASE_LOCK('tmp'));
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (ROW_COUNT());
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (SESSION_USER());
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (SLEEP(1));
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (SYSDATE());
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (SYSTEM_USER());
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (USER());
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (UUID());
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (UUID_SHORT());
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
INSERT INTO t1 VALUES (VERSION());
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Statement may not be safe to log in statement format.
|
||||||
|
DELETE FROM t1;
|
||||||
|
SET TIMESTAMP=1000000;
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(CURDATE()),
|
||||||
|
(CURRENT_DATE()),
|
||||||
|
(CURRENT_TIME()),
|
||||||
|
(CURRENT_TIMESTAMP()),
|
||||||
|
(CURTIME()),
|
||||||
|
(LOCALTIME()),
|
||||||
|
(LOCALTIMESTAMP()),
|
||||||
|
(NOW()),
|
||||||
|
(UNIX_TIMESTAMP()),
|
||||||
|
(UTC_DATE()),
|
||||||
|
(UTC_TIME()),
|
||||||
|
(UTC_TIMESTAMP());
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
1970-01-12
|
||||||
|
1970-01-12
|
||||||
|
16:46:40
|
||||||
|
1970-01-12 16:46:40
|
||||||
|
16:46:40
|
||||||
|
1970-01-12 16:46:40
|
||||||
|
1970-01-12 16:46:40
|
||||||
|
1970-01-12 16:46:40
|
||||||
|
1000000
|
||||||
|
1970-01-12
|
||||||
|
13:46:40
|
||||||
|
1970-01-12 13:46:40
|
||||||
|
DROP TABLE t1;
|
||||||
"End of tests"
|
"End of tests"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
-- source include/have_innodb.inc
|
-- source include/have_innodb.inc
|
||||||
-- source include/have_binlog_format_mixed_or_statement.inc
|
-- source include/have_binlog_format_statement.inc
|
||||||
|
|
||||||
# You cannot use `KILL' with the Embedded MySQL Server library,
|
# You cannot use `KILL' with the Embedded MySQL Server library,
|
||||||
# because the embedded server merely runs inside the threads of the host
|
# because the embedded server merely runs inside the threads of the host
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
# For both statement and row based bin logs 9/19/2005 [jbm]
|
# For both statement and row based bin logs 9/19/2005 [jbm]
|
||||||
|
|
||||||
-- source include/have_binlog_format_statement.inc
|
-- source include/have_binlog_format_statement.inc
|
||||||
|
|
||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
|
|
||||||
-- source extra/binlog_tests/mix_innodb_myisam_binlog.test
|
-- source extra/binlog_tests/mix_innodb_myisam_binlog.test
|
||||||
|
|
||||||
set @@session.binlog_format=statement;
|
set @@session.binlog_format=statement;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
--source include/have_log_bin.inc
|
--source include/have_log_bin.inc
|
||||||
--source include/have_binlog_format_row_or_statement.inc
|
# Test sets its own binlog_format, so we restrict it to run only once
|
||||||
|
--source include/have_binlog_format_row.inc
|
||||||
|
|
||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
|
|
||||||
# Get rid of previous tests binlog
|
# Get rid of previous tests binlog
|
||||||
--disable_query_log
|
--disable_query_log
|
||||||
|
@ -388,4 +388,56 @@ DELETE FROM t1 LIMIT 1;
|
|||||||
|
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
SET @@SESSION.SQL_MODE = @save_sql_mode;
|
SET @@SESSION.SQL_MODE = @save_sql_mode;
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#47995: Mark user functions as unsafe
|
||||||
|
#
|
||||||
|
# Test that the system functions that are supposed to be marked unsafe
|
||||||
|
# generate a warning. Each INSERT statement below should generate a
|
||||||
|
# warning.
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a VARCHAR(1000));
|
||||||
|
INSERT INTO t1 VALUES (CURRENT_USER()); #marked unsafe before BUG#47995
|
||||||
|
INSERT INTO t1 VALUES (FOUND_ROWS()); #marked unsafe before BUG#47995
|
||||||
|
INSERT INTO t1 VALUES (GET_LOCK('tmp', 1));
|
||||||
|
INSERT INTO t1 VALUES (IS_FREE_LOCK('tmp'));
|
||||||
|
INSERT INTO t1 VALUES (IS_USED_LOCK('tmp'));
|
||||||
|
INSERT INTO t1 VALUES (LOAD_FILE('../../std_data/words2.dat')); #marked unsafe before BUG#47995
|
||||||
|
INSERT INTO t1 VALUES (MASTER_POS_WAIT('dummy arg', 4711, 1));
|
||||||
|
INSERT INTO t1 VALUES (RELEASE_LOCK('tmp'));
|
||||||
|
INSERT INTO t1 VALUES (ROW_COUNT()); #marked unsafe before BUG#47995
|
||||||
|
INSERT INTO t1 VALUES (SESSION_USER()); #marked unsafe before BUG#47995
|
||||||
|
INSERT INTO t1 VALUES (SLEEP(1));
|
||||||
|
INSERT INTO t1 VALUES (SYSDATE());
|
||||||
|
INSERT INTO t1 VALUES (SYSTEM_USER()); #marked unsafe before BUG#47995
|
||||||
|
INSERT INTO t1 VALUES (USER()); #marked unsafe before BUG#47995
|
||||||
|
INSERT INTO t1 VALUES (UUID()); #marked unsafe before BUG#47995
|
||||||
|
INSERT INTO t1 VALUES (UUID_SHORT()); #marked unsafe before BUG#47995
|
||||||
|
INSERT INTO t1 VALUES (VERSION());
|
||||||
|
DELETE FROM t1;
|
||||||
|
|
||||||
|
# Since we replicate the TIMESTAMP variable, functions affected by the
|
||||||
|
# TIMESTAMP variable are safe to replicate. So we check that the
|
||||||
|
# following following functions depend on the TIMESTAMP variable and
|
||||||
|
# don't generate a warning.
|
||||||
|
|
||||||
|
SET TIMESTAMP=1000000;
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(CURDATE()),
|
||||||
|
(CURRENT_DATE()),
|
||||||
|
(CURRENT_TIME()),
|
||||||
|
(CURRENT_TIMESTAMP()),
|
||||||
|
(CURTIME()),
|
||||||
|
(LOCALTIME()),
|
||||||
|
(LOCALTIMESTAMP()),
|
||||||
|
(NOW()),
|
||||||
|
(UNIX_TIMESTAMP()),
|
||||||
|
(UTC_DATE()),
|
||||||
|
(UTC_TIME()),
|
||||||
|
(UTC_TIMESTAMP());
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo "End of tests"
|
--echo "End of tests"
|
||||||
|
@ -4,6 +4,7 @@ reset master;
|
|||||||
reset slave;
|
reset slave;
|
||||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||||
start slave;
|
start slave;
|
||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
create table t1 (a int primary key);
|
create table t1 (a int primary key);
|
||||||
create table t4 (a int primary key);
|
create table t4 (a int primary key);
|
||||||
insert into t1 values (1),(1);
|
insert into t1 values (1),(1);
|
||||||
|
@ -4,6 +4,7 @@ reset master;
|
|||||||
reset slave;
|
reset slave;
|
||||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||||
start slave;
|
start slave;
|
||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
create table t1(n int);
|
create table t1(n int);
|
||||||
insert into t1 values(get_lock("lock",2));
|
insert into t1 values(get_lock("lock",2));
|
||||||
select get_lock("lock",2);
|
select get_lock("lock",2);
|
||||||
|
26
mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result
Normal file
26
mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
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;
|
||||||
|
CREATE TABLE t1 (a VARCHAR(1000));
|
||||||
|
INSERT INTO t1 VALUES (CONNECTION_ID());
|
||||||
|
INSERT INTO t1 VALUES (CONNECTION_ID());
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(CURDATE()),
|
||||||
|
(CURRENT_DATE()),
|
||||||
|
(CURRENT_TIME()),
|
||||||
|
(CURRENT_TIMESTAMP()),
|
||||||
|
(CURTIME()),
|
||||||
|
(LOCALTIME()),
|
||||||
|
(LOCALTIMESTAMP()),
|
||||||
|
(NOW()),
|
||||||
|
(UNIX_TIMESTAMP()),
|
||||||
|
(UTC_DATE()),
|
||||||
|
(UTC_TIME()),
|
||||||
|
(UTC_TIMESTAMP());
|
||||||
|
INSERT INTO t1 VALUES (RAND());
|
||||||
|
INSERT INTO t1 VALUES (LAST_INSERT_ID());
|
||||||
|
Comparing tables master:test.t1 and slave:test.t1
|
||||||
|
DROP TABLE t1;
|
@ -4,6 +4,7 @@ reset master;
|
|||||||
reset slave;
|
reset slave;
|
||||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||||
start slave;
|
start slave;
|
||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
create table t1 (word char(20) not null);
|
create table t1 (word char(20) not null);
|
||||||
load data infile '../../std_data/words.dat' into table t1;
|
load data infile '../../std_data/words.dat' into table t1;
|
||||||
load data local infile 'MYSQL_TEST_DIR/std_data/words.dat' into table t1;
|
load data local infile 'MYSQL_TEST_DIR/std_data/words.dat' into table t1;
|
||||||
|
@ -4,6 +4,7 @@ reset master;
|
|||||||
reset slave;
|
reset slave;
|
||||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||||
start slave;
|
start slave;
|
||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
DROP TABLE IF EXISTS t2;
|
DROP TABLE IF EXISTS t2;
|
||||||
DROP TABLE IF EXISTS t3;
|
DROP TABLE IF EXISTS t3;
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
-- source include/master-slave.inc
|
-- source include/master-slave.inc
|
||||||
|
|
||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
|
|
||||||
connection master;
|
connection master;
|
||||||
create table t1 (a int primary key);
|
create table t1 (a int primary key);
|
||||||
create table t4 (a int primary key);
|
create table t4 (a int primary key);
|
||||||
@ -14,19 +16,15 @@ create table t4 (a int primary key);
|
|||||||
--error 1022, ER_DUP_ENTRY
|
--error 1022, ER_DUP_ENTRY
|
||||||
insert into t1 values (1),(1);
|
insert into t1 values (1),(1);
|
||||||
insert into t4 values (1),(2);
|
insert into t4 values (1),(2);
|
||||||
save_master_pos;
|
|
||||||
connection slave;
|
|
||||||
# as the t1 table is ignored on the slave, the slave should be able to sync
|
# as the t1 table is ignored on the slave, the slave should be able to sync
|
||||||
sync_with_master;
|
sync_slave_with_master;
|
||||||
# check that the table has been ignored, because otherwise the test is nonsense
|
# check that the table has been ignored, because otherwise the test is nonsense
|
||||||
show tables like 't1';
|
show tables like 't1';
|
||||||
show tables like 't4';
|
show tables like 't4';
|
||||||
SELECT * FROM test.t4 ORDER BY a;
|
SELECT * FROM test.t4 ORDER BY a;
|
||||||
connection master;
|
connection master;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
save_master_pos;
|
sync_slave_with_master;
|
||||||
connection slave;
|
|
||||||
sync_with_master;
|
|
||||||
|
|
||||||
# Now test that even critical errors (connection killed)
|
# Now test that even critical errors (connection killed)
|
||||||
# are ignored if rules allow it.
|
# are ignored if rules allow it.
|
||||||
@ -50,18 +48,17 @@ kill @id;
|
|||||||
drop table t2,t3;
|
drop table t2,t3;
|
||||||
insert into t4 values (3),(4);
|
insert into t4 values (3),(4);
|
||||||
connection master;
|
connection master;
|
||||||
|
# The get_lock function causes warning for unsafe statement.
|
||||||
|
--disable_warnings
|
||||||
--error 0,1317,2013
|
--error 0,1317,2013
|
||||||
reap;
|
reap;
|
||||||
|
--enable_warnings
|
||||||
connection master1;
|
connection master1;
|
||||||
save_master_pos;
|
sync_slave_with_master;
|
||||||
connection slave;
|
|
||||||
sync_with_master;
|
|
||||||
SELECT * FROM test.t4 ORDER BY a;
|
SELECT * FROM test.t4 ORDER BY a;
|
||||||
|
|
||||||
connection master1;
|
connection master1;
|
||||||
DROP TABLE test.t4;
|
DROP TABLE test.t4;
|
||||||
save_master_pos;
|
sync_slave_with_master;
|
||||||
connection slave;
|
|
||||||
sync_with_master;
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
# Adding comment for force manual merge 5.0 -> wl1012. delete me if needed
|
# Adding comment for force manual merge 5.0 -> wl1012. delete me if needed
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
source include/master-slave.inc;
|
source include/master-slave.inc;
|
||||||
|
|
||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
|
|
||||||
create table t1(n int);
|
create table t1(n int);
|
||||||
|
# Use of get_lock gives a warning for unsafeness if binlog_format=statement
|
||||||
|
--disable_warnings
|
||||||
insert into t1 values(get_lock("lock",2));
|
insert into t1 values(get_lock("lock",2));
|
||||||
|
--enable_warnings
|
||||||
dirty_close master;
|
dirty_close master;
|
||||||
connection master1;
|
connection master1;
|
||||||
select get_lock("lock",2);
|
select get_lock("lock",2);
|
||||||
|
53
mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test
Normal file
53
mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# ==== Purpose ====
|
||||||
|
#
|
||||||
|
# Test that nondeterministic system functions are correctly replicated.
|
||||||
|
#
|
||||||
|
# (Some functions are only correctly replicated if binlog_format=MIXED
|
||||||
|
# or ROW. See binlog_unsafe.test for a test that those variables are
|
||||||
|
# indeed unsafe.)
|
||||||
|
#
|
||||||
|
# ==== Implementation ====
|
||||||
|
#
|
||||||
|
# We insert the values of each unsafe function into a table. Then we
|
||||||
|
# replicate and check that the table is identical on slave.
|
||||||
|
#
|
||||||
|
# ==== Related bugs ====
|
||||||
|
#
|
||||||
|
# BUG#47995
|
||||||
|
|
||||||
|
--source include/master-slave.inc
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a VARCHAR(1000));
|
||||||
|
|
||||||
|
# We replicate the connection_id in the query_log_event
|
||||||
|
INSERT INTO t1 VALUES (CONNECTION_ID());
|
||||||
|
--connection master1
|
||||||
|
INSERT INTO t1 VALUES (CONNECTION_ID());
|
||||||
|
|
||||||
|
# We replicate the TIMESTAMP variable, so the following functions that
|
||||||
|
# are affected by the TIMESTAMP variable should be safe to replicate.
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(CURDATE()),
|
||||||
|
(CURRENT_DATE()),
|
||||||
|
(CURRENT_TIME()),
|
||||||
|
(CURRENT_TIMESTAMP()),
|
||||||
|
(CURTIME()),
|
||||||
|
(LOCALTIME()),
|
||||||
|
(LOCALTIMESTAMP()),
|
||||||
|
(NOW()),
|
||||||
|
(UNIX_TIMESTAMP()),
|
||||||
|
(UTC_DATE()),
|
||||||
|
(UTC_TIME()),
|
||||||
|
(UTC_TIMESTAMP());
|
||||||
|
|
||||||
|
# We replicate the random seed in a rand_log_event
|
||||||
|
INSERT INTO t1 VALUES (RAND());
|
||||||
|
# We replicate the last_insert_id in an intvar_log_event
|
||||||
|
INSERT INTO t1 VALUES (LAST_INSERT_ID());
|
||||||
|
|
||||||
|
--sync_slave_with_master
|
||||||
|
--let $diff_table_1= master:test.t1
|
||||||
|
--let $diff_table_2= slave:test.t1
|
||||||
|
--source include/diff_tables.inc
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
@ -5,6 +5,8 @@
|
|||||||
--source include/have_binlog_format_mixed_or_statement.inc
|
--source include/have_binlog_format_mixed_or_statement.inc
|
||||||
--source include/master-slave.inc
|
--source include/master-slave.inc
|
||||||
|
|
||||||
|
CALL mtr.add_suppression("Statement may not be safe to log in statement format.");
|
||||||
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
DROP TABLE IF EXISTS t2;
|
DROP TABLE IF EXISTS t2;
|
||||||
@ -89,7 +91,11 @@ end
|
|||||||
|
|
|
|
||||||
|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
|
# The trigger causes a warning for unsafe statement when
|
||||||
|
# binlog_format=statement since it uses get_lock.
|
||||||
|
--disable_warnings
|
||||||
insert into t1 set a = now();
|
insert into t1 set a = now();
|
||||||
|
--enable_warnings
|
||||||
select a=b && a=c from t1;
|
select a=b && a=c from t1;
|
||||||
let $time=`select a from t1`;
|
let $time=`select a from t1`;
|
||||||
|
|
||||||
@ -135,7 +141,11 @@ disconnect con2;
|
|||||||
truncate table t1;
|
truncate table t1;
|
||||||
drop trigger t1_first;
|
drop trigger t1_first;
|
||||||
|
|
||||||
|
# The trigger causes a warning for unsafe statement when
|
||||||
|
# binlog_format=statement since it uses get_lock.
|
||||||
|
--disable_warnings
|
||||||
insert into t1 values ("2003-03-03","2003-03-03","2003-03-03"),(bug12480(),bug12480(),bug12480()),(now(),now(),now());
|
insert into t1 values ("2003-03-03","2003-03-03","2003-03-03"),(bug12480(),bug12480(),bug12480()),(now(),now(),now());
|
||||||
|
--enable_warnings
|
||||||
select a=b && a=c from t1;
|
select a=b && a=c from t1;
|
||||||
|
|
||||||
drop function bug12480;
|
drop function bug12480;
|
||||||
|
@ -3524,6 +3524,7 @@ Create_func_get_lock Create_func_get_lock::s_singleton;
|
|||||||
Item*
|
Item*
|
||||||
Create_func_get_lock::create(THD *thd, Item *arg1, Item *arg2)
|
Create_func_get_lock::create(THD *thd, Item *arg1, Item *arg2)
|
||||||
{
|
{
|
||||||
|
thd->lex->set_stmt_unsafe();
|
||||||
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||||
return new (thd->mem_root) Item_func_get_lock(arg1, arg2);
|
return new (thd->mem_root) Item_func_get_lock(arg1, arg2);
|
||||||
}
|
}
|
||||||
@ -3635,6 +3636,7 @@ Create_func_is_free_lock Create_func_is_free_lock::s_singleton;
|
|||||||
Item*
|
Item*
|
||||||
Create_func_is_free_lock::create(THD *thd, Item *arg1)
|
Create_func_is_free_lock::create(THD *thd, Item *arg1)
|
||||||
{
|
{
|
||||||
|
thd->lex->set_stmt_unsafe();
|
||||||
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||||
return new (thd->mem_root) Item_func_is_free_lock(arg1);
|
return new (thd->mem_root) Item_func_is_free_lock(arg1);
|
||||||
}
|
}
|
||||||
@ -3645,6 +3647,7 @@ Create_func_is_used_lock Create_func_is_used_lock::s_singleton;
|
|||||||
Item*
|
Item*
|
||||||
Create_func_is_used_lock::create(THD *thd, Item *arg1)
|
Create_func_is_used_lock::create(THD *thd, Item *arg1)
|
||||||
{
|
{
|
||||||
|
thd->lex->set_stmt_unsafe();
|
||||||
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||||
return new (thd->mem_root) Item_func_is_used_lock(arg1);
|
return new (thd->mem_root) Item_func_is_used_lock(arg1);
|
||||||
}
|
}
|
||||||
@ -3961,6 +3964,8 @@ Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name,
|
|||||||
Item *func= NULL;
|
Item *func= NULL;
|
||||||
int arg_count= 0;
|
int arg_count= 0;
|
||||||
|
|
||||||
|
thd->lex->set_stmt_unsafe();
|
||||||
|
|
||||||
if (item_list != NULL)
|
if (item_list != NULL)
|
||||||
arg_count= item_list->elements;
|
arg_count= item_list->elements;
|
||||||
|
|
||||||
@ -4203,6 +4208,7 @@ Create_func_release_lock Create_func_release_lock::s_singleton;
|
|||||||
Item*
|
Item*
|
||||||
Create_func_release_lock::create(THD *thd, Item *arg1)
|
Create_func_release_lock::create(THD *thd, Item *arg1)
|
||||||
{
|
{
|
||||||
|
thd->lex->set_stmt_unsafe();
|
||||||
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||||
return new (thd->mem_root) Item_func_release_lock(arg1);
|
return new (thd->mem_root) Item_func_release_lock(arg1);
|
||||||
}
|
}
|
||||||
@ -4325,6 +4331,7 @@ Create_func_sleep Create_func_sleep::s_singleton;
|
|||||||
Item*
|
Item*
|
||||||
Create_func_sleep::create(THD *thd, Item *arg1)
|
Create_func_sleep::create(THD *thd, Item *arg1)
|
||||||
{
|
{
|
||||||
|
thd->lex->set_stmt_unsafe();
|
||||||
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||||
return new (thd->mem_root) Item_func_sleep(arg1);
|
return new (thd->mem_root) Item_func_sleep(arg1);
|
||||||
}
|
}
|
||||||
@ -4591,6 +4598,7 @@ Create_func_version Create_func_version::s_singleton;
|
|||||||
Item*
|
Item*
|
||||||
Create_func_version::create(THD *thd)
|
Create_func_version::create(THD *thd)
|
||||||
{
|
{
|
||||||
|
thd->lex->set_stmt_unsafe();
|
||||||
return new (thd->mem_root) Item_static_string_func("version()",
|
return new (thd->mem_root) Item_static_string_func("version()",
|
||||||
server_version,
|
server_version,
|
||||||
(uint) strlen(server_version),
|
(uint) strlen(server_version),
|
||||||
|
@ -1827,8 +1827,9 @@ String *Item_func_database::val_str(String *str)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@todo
|
@note USER() is replicated correctly if binlog_format=ROW or (as of
|
||||||
make USER() replicate properly (currently it is replicated to "")
|
BUG#28086) binlog_format=MIXED, but is incorrectly replicated to ''
|
||||||
|
if binlog_format=STATEMENT.
|
||||||
*/
|
*/
|
||||||
bool Item_func_user::init(const char *user, const char *host)
|
bool Item_func_user::init(const char *user, const char *host)
|
||||||
{
|
{
|
||||||
|
@ -7523,6 +7523,14 @@ function_call_nonkeyword:
|
|||||||
}
|
}
|
||||||
| SYSDATE optional_braces
|
| SYSDATE optional_braces
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Unlike other time-related functions, SYSDATE() is
|
||||||
|
replication-unsafe because it is not affected by the
|
||||||
|
TIMESTAMP variable. It is unsafe even if
|
||||||
|
sysdate_is_now=1, because the slave may have
|
||||||
|
sysdate_is_now=0.
|
||||||
|
*/
|
||||||
|
Lex->set_stmt_unsafe();
|
||||||
if (global_system_variables.sysdate_is_now == 0)
|
if (global_system_variables.sysdate_is_now == 0)
|
||||||
$$= new (YYTHD->mem_root) Item_func_sysdate_local();
|
$$= new (YYTHD->mem_root) Item_func_sysdate_local();
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user