diff --git a/mysql-test/suite/sys_vars/r/set_server_id_inside_transaction.result b/mysql-test/suite/sys_vars/r/set_server_id_inside_transaction.result new file mode 100644 index 0000000000000..3e7710e3b8683 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/set_server_id_inside_transaction.result @@ -0,0 +1,76 @@ +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +# +# Test that SET @@session.server_id fails inside explicit transaction +# +BEGIN; +INSERT INTO t1 VALUES (1); +SET @@session.server_id = 100; +ERROR HY000: Cannot set @@session.server_id within a transaction +ROLLBACK; +# +# Test that SET @@session.server_id works outside transaction +# +SET @@session.server_id = 100; +SELECT @@session.server_id; +@@session.server_id +100 +# +# Test that SET @@session.server_id fails with autocommit=0 +# +SET autocommit = 0; +INSERT INTO t1 VALUES (2); +SET @@session.server_id = 200; +ERROR HY000: Cannot set @@session.server_id within a transaction +ROLLBACK; +SET autocommit = 1; +# +# Test that SET @@session.server_id works after COMMIT +# +BEGIN; +INSERT INTO t1 VALUES (3); +COMMIT; +SET @@session.server_id = 300; +SELECT @@session.server_id; +@@session.server_id +300 +# +# Test that SET @@session.server_id fails inside a trigger +# +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +CREATE TRIGGER tr1 BEFORE INSERT ON t2 FOR EACH ROW +SET @@session.server_id = 100; +INSERT INTO t2 VALUES (1); +ERROR HY000: Cannot set @@session.server_id within a trigger or stored program +DROP TRIGGER tr1; +DROP TABLE t2; +# +# Test that SET @@session.server_id fails inside a stored procedure +# called within a transaction +# +CREATE PROCEDURE sp1() +BEGIN +SET @@session.server_id = 100; +END// +BEGIN; +CALL sp1(); +ERROR HY000: Cannot set @@session.server_id within a transaction +ROLLBACK; +DROP PROCEDURE sp1; +# +# Test that SET @@session.server_id fails inside a stored procedure +# that starts its own transaction +# +CREATE PROCEDURE sp2() +BEGIN +START TRANSACTION; +INSERT INTO t1 VALUES (1); +SET @@session.server_id = 100; +COMMIT; +END// +CALL sp2(); +ERROR HY000: Cannot set @@session.server_id within a transaction +DROP PROCEDURE sp2; +# +# Cleanup +# +DROP TABLE t1; diff --git a/mysql-test/suite/sys_vars/t/set_server_id_inside_transaction.test b/mysql-test/suite/sys_vars/t/set_server_id_inside_transaction.test new file mode 100644 index 0000000000000..865542b400904 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/set_server_id_inside_transaction.test @@ -0,0 +1,94 @@ +--source include/have_innodb.inc + +# +# MDEV-27837: Disallow SET @@session.server_id within transaction +# + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; + +--echo # +--echo # Test that SET @@session.server_id fails inside explicit transaction +--echo # +BEGIN; +INSERT INTO t1 VALUES (1); +--error ER_CANT_SET_SERVER_ID_IN_TRANSACTION +SET @@session.server_id = 100; +ROLLBACK; + +--echo # +--echo # Test that SET @@session.server_id works outside transaction +--echo # +SET @@session.server_id = 100; +SELECT @@session.server_id; + +--echo # +--echo # Test that SET @@session.server_id fails with autocommit=0 +--echo # +SET autocommit = 0; +INSERT INTO t1 VALUES (2); +--error ER_CANT_SET_SERVER_ID_IN_TRANSACTION +SET @@session.server_id = 200; +ROLLBACK; +SET autocommit = 1; + +--echo # +--echo # Test that SET @@session.server_id works after COMMIT +--echo # +BEGIN; +INSERT INTO t1 VALUES (3); +COMMIT; +SET @@session.server_id = 300; +SELECT @@session.server_id; + +--echo # +--echo # Test that SET @@session.server_id fails inside a trigger +--echo # +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +CREATE TRIGGER tr1 BEFORE INSERT ON t2 FOR EACH ROW + SET @@session.server_id = 100; +--error ER_CANT_SET_SERVER_ID_IN_SUBSTATEMENT +INSERT INTO t2 VALUES (1); +DROP TRIGGER tr1; +DROP TABLE t2; + +--echo # +--echo # Test that SET @@session.server_id fails inside a stored procedure +--echo # called within a transaction +--echo # +--delimiter // + +CREATE PROCEDURE sp1() +BEGIN + SET @@session.server_id = 100; +END// + +--delimiter ; + +BEGIN; +--error ER_CANT_SET_SERVER_ID_IN_TRANSACTION +CALL sp1(); +ROLLBACK; +DROP PROCEDURE sp1; + +--echo # +--echo # Test that SET @@session.server_id fails inside a stored procedure +--echo # that starts its own transaction +--echo # +--delimiter // +CREATE PROCEDURE sp2() +BEGIN + START TRANSACTION; + INSERT INTO t1 VALUES (1); + SET @@session.server_id = 100; + COMMIT; +END// +--delimiter ; +--error ER_CANT_SET_SERVER_ID_IN_TRANSACTION +CALL sp2(); +DROP PROCEDURE sp2; + +--echo # +--echo # Cleanup +--echo # +DROP TABLE t1; + diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index f0273c6cb7a82..ac42282884b7c 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -10036,3 +10036,7 @@ ER_REMOVED_ORPHAN_TRIGGER ER_STORAGE_ENGINE_DISABLED eng "Storage engine %s is disabled" spa "El motor de almacenaje %s está desactivado" +ER_CANT_SET_SERVER_ID_IN_TRANSACTION + eng "Cannot set @@session.server_id within a transaction" +ER_CANT_SET_SERVER_ID_IN_SUBSTATEMENT + eng "Cannot set @@session.server_id within a trigger or stored program" diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 5fe3eb4586b20..2c7e8330b6d84 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3375,6 +3375,13 @@ static bool check_server_id(sys_var *self, THD *thd, set_var *var) return true; } #endif /* WITH_WSREP */ + + if (error_if_in_trans_or_substatement( + thd, + ER_CANT_SET_SERVER_ID_IN_SUBSTATEMENT, + ER_CANT_SET_SERVER_ID_IN_TRANSACTION)) + return true; + return false; }