diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 682cc2e82e2..d95499fe3ba 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1267,4 +1267,28 @@ CREATE INDEX i1 on t1 (a(3)); SELECT * FROM t1 WHERE a = 'abcde'; a DROP TABLE t1; +# +# BUG #26288: savepoint are not deleted on comit, if the transaction +# was otherwise empty +# +BEGIN; +SAVEPOINT s1; +COMMIT; +RELEASE SAVEPOINT s1; +ERROR 42000: SAVEPOINT s1 does not exist +BEGIN; +SAVEPOINT s2; +COMMIT; +ROLLBACK TO SAVEPOINT s2; +ERROR 42000: SAVEPOINT s2 does not exist +BEGIN; +SAVEPOINT s3; +ROLLBACK; +RELEASE SAVEPOINT s3; +ERROR 42000: SAVEPOINT s3 does not exist +BEGIN; +SAVEPOINT s4; +ROLLBACK; +ROLLBACK TO SAVEPOINT s4; +ERROR 42000: SAVEPOINT s4 does not exist End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index b4fc425cb7c..512f7fc7fe2 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -1025,4 +1025,33 @@ CREATE INDEX i1 on t1 (a(3)); SELECT * FROM t1 WHERE a = 'abcde'; DROP TABLE t1; + +--echo # +--echo # BUG #26288: savepoint are not deleted on comit, if the transaction +--echo # was otherwise empty +--echo # +BEGIN; +SAVEPOINT s1; +COMMIT; +--error 1305 +RELEASE SAVEPOINT s1; + +BEGIN; +SAVEPOINT s2; +COMMIT; +--error 1305 +ROLLBACK TO SAVEPOINT s2; + +BEGIN; +SAVEPOINT s3; +ROLLBACK; +--error 1305 +RELEASE SAVEPOINT s3; + +BEGIN; +SAVEPOINT s4; +ROLLBACK; +--error 1305 +ROLLBACK TO SAVEPOINT s4; + --echo End of 5.0 tests diff --git a/sql/handler.cc b/sql/handler.cc index d069d56caae..63f652fc2b4 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -730,6 +730,16 @@ end: if (is_real_trans) start_waiting_global_read_lock(thd); } + else if (all) + { + /* + A COMMIT of an empty transaction. There may be savepoints. + Destroy them. If the transaction is not empty + savepoints are cleared in ha_commit_one_phase() + or ha_rollback_trans(). + */ + thd->transaction.cleanup(); + } #endif /* USING_TRANSACTIONS */ DBUG_RETURN(error); } @@ -825,11 +835,11 @@ int ha_rollback_trans(THD *thd, bool all) thd->transaction.xid_state.xid.null(); } if (all) - { thd->variables.tx_isolation=thd->session_tx_isolation; - thd->transaction.cleanup(); - } } + /* Always cleanup. Even if there nht==0. There may be savepoints. */ + if (all) + thd->transaction.cleanup(); #endif /* USING_TRANSACTIONS */ if (all) thd->transaction_rollback_request= FALSE;