Commit 2f78abd2 authored by Sven Sandberg's avatar Sven Sandberg

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.
parent 7524b961
-- 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; ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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) ...@@ -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
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); ...@@ -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);
......
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'); ...@@ -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: ...@@ -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"
-- 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 @@ ...@@ -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;
......
--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; ...@@ -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; ...@@ -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; ...@@ -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);
......
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; ...@@ -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; ...@@ -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 @@ ...@@ -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); ...@@ -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; ...@@ -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
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);
......
# ==== 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 @@ ...@@ -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 ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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, ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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) ...@@ -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: ...@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment