From 127ed74fd2c3398e2ebc6602291250a5db4b2ec4 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Fri, 5 Jun 2020 16:41:25 +0300 Subject: [PATCH] MDEV-22420 DDL on temporary object is prohibited when XA is in prepare state The parser must reject DDL operations on temporary objects when they may modify or alter such object, including temporary tables and sequences. The rejection is regardless (has been already in place for bin-loggable DML:s) of the binlogging capability of the server or connection. The patch implements the requirement. A binlog test is added. --- .../binlog/r/binlog_empty_xa_prepared.result | 31 ++++++++++++++++ .../binlog/t/binlog_empty_xa_prepared.test | 35 +++++++++++++++++++ sql/sql_parse.cc | 2 ++ 3 files changed, 68 insertions(+) create mode 100644 mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result create mode 100644 mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test diff --git a/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result b/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result new file mode 100644 index 00000000000..eb96f7bb984 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result @@ -0,0 +1,31 @@ +CREATE TEMPORARY SEQUENCE seq_1; +XA START '3'; +CREATE TEMPORARY TABLE tmp_1(c INT); +XA END '3'; +XA PREPARE '3'; +DROP TEMPORARY TABLE tmp_1; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +ALTER TABLE tmp_1 DROP COLUMN c; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +DROP TEMPORARY SEQUENCE seq_1; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +ALTER SEQUENCE seq_1 INCREMENT BY 1; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +CREATE TEMPORARY TABLE tmp_2(c INT); +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +CREATE TEMPORARY SEQUENCE seq_2; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +XA ROLLBACK '3'; +# Proof of correct logging incl empty XA-PREPARE +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY SEQUENCE seq_1 +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp_1(c INT) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # XA START X'33',X'',1 GTID #-#-# +master-bin.000001 # Query # # XA END X'33',X'',1 +master-bin.000001 # XA_prepare # # XA PREPARE X'33',X'',1 +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # XA ROLLBACK X'33',X'',1 diff --git a/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test new file mode 100644 index 00000000000..7f923f71f81 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test @@ -0,0 +1,35 @@ +# The test verifies execution and binary logging of user XA that produce empty +# XA-PREPARE group of events. + +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc + + +# MDEV-22420 DDL on temporary object is prohibited when XA is in prepare state + +# Temporary sequnce may not be created within a transaction +CREATE TEMPORARY SEQUENCE seq_1; + +XA START '3'; +CREATE TEMPORARY TABLE tmp_1(c INT); +XA END '3'; +XA PREPARE '3'; +--error ER_XAER_RMFAIL +DROP TEMPORARY TABLE tmp_1; +--error ER_XAER_RMFAIL +ALTER TABLE tmp_1 DROP COLUMN c; +--error ER_XAER_RMFAIL +DROP TEMPORARY SEQUENCE seq_1; +--error ER_XAER_RMFAIL +ALTER SEQUENCE seq_1 INCREMENT BY 1; + +--error ER_XAER_RMFAIL +CREATE TEMPORARY TABLE tmp_2(c INT); +--error ER_XAER_RMFAIL +CREATE TEMPORARY SEQUENCE seq_2; + +# Cleanup +XA ROLLBACK '3'; + +--echo # Proof of correct logging incl empty XA-PREPARE +--source include/show_binlog_events.inc diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e35ee16cf4b..cd60472e81c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4890,6 +4890,8 @@ mysql_execute_command(THD *thd) } else { + if (thd->transaction->xid_state.check_has_uncommitted_xa()) + goto error; status_var_decrement(thd->status_var.com_stat[lex->sql_command]); status_var_increment(thd->status_var.com_drop_tmp_table);