diff --git a/include/sqlite/transaction.hpp b/include/sqlite/transaction.hpp index cfecbbf..8e3495a 100644 --- a/include/sqlite/transaction.hpp +++ b/include/sqlite/transaction.hpp @@ -100,10 +100,17 @@ namespace sqlite{ * \return \c true if transaction is still active, \c false otherwise */ bool isActive() const { return m_isActive; } + /** \brief Allow to check if transaction handled by this object is + * currently in the middle of a COMMIT/Rollback operation. It is used + * for the handling of exceptions during commit/rollback operations. + * \return \c true if transaction is committing/rolling back, \c false otherwise + */ + bool isEnding() const { return m_isEnding; } private: void exec(std::string const &); connection & m_con; bool m_isActive; ///< if \c true there is a transaction currently opened + bool m_isEnding; ///< if \c true there is a transaction is currently ending }; } diff --git a/src/sqlite/transaction.cpp b/src/sqlite/transaction.cpp index 994e037..3cda5dd 100644 --- a/src/sqlite/transaction.cpp +++ b/src/sqlite/transaction.cpp @@ -42,8 +42,18 @@ namespace sqlite{ } transaction::~transaction(){ + // when the transaction is stuck ending, the commit/rollback failed + // and we don't want to take further action, we must assume there is + // nothing we can do. + if (m_isEnding) { + return; + } if (m_isActive) { - rollback(); + try { + rollback(); + } catch (...) { + // We can't recover in the destructor, hope for the best and continue. + } } } @@ -61,17 +71,23 @@ namespace sqlite{ } void transaction::end(){ + m_isEnding = true; exec("END TRANSACTION"); + m_isEnding = false; m_isActive = false; } void transaction::commit(){ + m_isEnding = true; exec("COMMIT TRANSACTION"); + m_isEnding = false; m_isActive = false; } void transaction::rollback(){ + m_isEnding = true; exec("ROLLBACK TRANSACTION"); + m_isEnding = false; m_isActive = false; }