List:Commits« Previous MessageNext Message »
From:Jon Olav Hauglid Date:March 25 2011 3:14pm
Subject:bzr push into mysql-trunk branch (jon.hauglid:3326 to 3327) Bug#11766752
View as plain text  
 3327 Jon Olav Hauglid	2011-03-25
      Bug #11766752 (former 59936)
      Multiple XA assertions - transactional statement fuzzer
      
      The problem was that the server for several statements did not check
      the state of the current XA transaction (if any) before trying to
      execute the statement. Specifically, you are not supposed to do
      anything other than XA PREPARE / XA COMMIT ONE PHASE when in IDLE state,
      or anything other than XA COMMIT / XA ROLLBACK in PREPARED state.
      
      The assertions triggered by the testcase posted in the bug report,
      was triggered by trying to access a table or rollback to a savepoint
      when the current XA transaction was in PREPARED state.
      
      This patch fixes the problem by reporting ER_XAER_RMFAIL error if
      1) A statement is issued which requires a table to be opened
         when XA state is IDLE or PREPARED.
      2) SAVEPOINT or ROLLBACK TO SAVEPOINT is executed with an active
         XA transaction. (Similar to what is already done for COMMIT/ROLLBACK)
      
      These are incompatible changes and must be reflected in the
      documentation.
      
      Test case added to xa.test.
      Also verified with the C testcase posted on the bug report.

    modified:
      mysql-test/r/xa.result
      mysql-test/t/xa.test
      sql/sql_base.cc
      sql/transaction.cc
 3326 Georgi Kodinov	2011-03-25 [merge]
      merge

    added:
      mysql-test/r/tablespace.result
      mysql-test/std_data/cluster_7022_table.MYD
      mysql-test/std_data/cluster_7022_table.MYI
      mysql-test/std_data/cluster_7022_table.frm
      mysql-test/t/tablespace.test
    modified:
      include/mysql_com.h
      sql/handler.h
      sql/sql_show.cc
      sql/sql_table.cc
      sql/table.cc
      sql/table.h
      sql/unireg.cc
=== modified file 'mysql-test/r/xa.result'
--- a/mysql-test/r/xa.result	2011-02-14 13:16:31 +0000
+++ b/mysql-test/r/xa.result	2011-03-25 15:13:41 +0000
@@ -166,3 +166,35 @@ ERROR XA102: XA_RBDEADLOCK: Transaction
 XA END 'b';
 XA ROLLBACK 'b';
 DROP TABLE t1;
+#
+# Bug#11766752 59936: multiple xa assertions - transactional
+#              statement fuzzer
+#
+CREATE TABLE t1 (a INT) engine=InnoDB;
+XA START 'a';
+INSERT INTO t1 VALUES (1);
+SAVEPOINT savep;
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  ACTIVE state
+XA END 'a';
+SELECT * FROM t1;
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  IDLE state
+INSERT INTO t1 VALUES (2);
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  IDLE state
+SAVEPOINT savep;
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  IDLE state
+SET @a=(SELECT * FROM t1);
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  IDLE state
+XA PREPARE 'a';
+SELECT * FROM t1;
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  PREPARED state
+INSERT INTO t1 VALUES (2);
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  PREPARED state
+SAVEPOINT savep;
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  PREPARED state
+SET @a=(SELECT * FROM t1);
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  PREPARED state
+XA COMMIT 'a';
+SELECT * FROM t1;
+a
+1
+DROP TABLE t1;

=== modified file 'mysql-test/t/xa.test'
--- a/mysql-test/t/xa.test	2011-02-14 13:16:31 +0000
+++ b/mysql-test/t/xa.test	2011-03-25 15:13:41 +0000
@@ -287,6 +287,43 @@ DROP TABLE t1;
 disconnect con1;
 
 
+--echo #
+--echo # Bug#11766752 59936: multiple xa assertions - transactional
+--echo #              statement fuzzer
+--echo #
+
+CREATE TABLE t1 (a INT) engine=InnoDB;
+XA START 'a';
+INSERT INTO t1 VALUES (1);
+
+--error ER_XAER_RMFAIL
+SAVEPOINT savep;
+
+XA END 'a';
+--error ER_XAER_RMFAIL
+SELECT * FROM t1;
+--error ER_XAER_RMFAIL
+INSERT INTO t1 VALUES (2);
+--error ER_XAER_RMFAIL
+SAVEPOINT savep;
+--error ER_XAER_RMFAIL
+SET @a=(SELECT * FROM t1);
+
+XA PREPARE 'a';
+--error ER_XAER_RMFAIL
+SELECT * FROM t1;          # used to cause InnoDB assert
+--error ER_XAER_RMFAIL
+INSERT INTO t1 VALUES (2); # used to cause InnoDB assert
+--error ER_XAER_RMFAIL
+SAVEPOINT savep;
+--error ER_XAER_RMFAIL
+SET @a=(SELECT * FROM t1); # used to cause InnoDB assert
+
+XA COMMIT 'a';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+
 # Wait till all disconnects are completed
 --source include/wait_until_count_sessions.inc
 

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2011-03-17 17:39:31 +0000
+++ b/sql/sql_base.cc	2011-03-25 15:13:41 +0000
@@ -4771,6 +4771,14 @@ bool open_tables(THD *thd, TABLE_LIST **
   bool has_prelocking_list;
   DBUG_ENTER("open_tables");
 
+  /* Accessing data in XA_IDLE or XA_PREPARED is not allowed. */
+  enum xa_states xa_state= thd->transaction.xid_state.xa_state;
+  if (*start && (xa_state == XA_IDLE || xa_state == XA_PREPARED))
+  {
+    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+    DBUG_RETURN(true);
+  }
+
   /*
     temporary mem_root for new .frm parsing.
     TODO: variables for size

=== modified file 'sql/transaction.cc'
--- a/sql/transaction.cc	2011-03-22 11:44:40 +0000
+++ b/sql/transaction.cc	2011-03-25 15:13:41 +0000
@@ -358,6 +358,13 @@ bool trans_savepoint(THD *thd, LEX_STRIN
       !opt_using_transactions)
     DBUG_RETURN(FALSE);
 
+  enum xa_states xa_state= thd->transaction.xid_state.xa_state;
+  if (xa_state != XA_NOTR)
+  {
+    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+    DBUG_RETURN(TRUE);
+  }
+
   sv= find_savepoint(thd, name);
 
   if (*sv) /* old savepoint of the same name exists */
@@ -431,6 +438,13 @@ bool trans_rollback_to_savepoint(THD *th
     DBUG_RETURN(TRUE);
   }
 
+  enum xa_states xa_state= thd->transaction.xid_state.xa_state;
+  if (xa_state != XA_NOTR)
+  {
+    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+    DBUG_RETURN(TRUE);
+  }
+
   if (ha_rollback_to_savepoint(thd, sv))
     res= TRUE;
   else if (((thd->variables.option_bits & OPTION_KEEP_LOG) ||

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (jon.hauglid:3326 to 3327) Bug#11766752Jon Olav Hauglid25 Mar