summaryrefslogtreecommitdiff
path: root/src/libs/sqlite
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2018-02-05 11:23:36 +0100
committerMarco Bubke <marco.bubke@qt.io>2018-02-14 15:03:22 +0000
commitdfb9e4355f14afd9b543b9967aa3095eb6b431eb (patch)
tree5cc3649f5087c8f618e3d9fc27c173cf725f99d3 /src/libs/sqlite
parentf6f11b53a75012c6530a4bda8edd2e66b030121f (diff)
downloadqt-creator-dfb9e4355f14afd9b543b9967aa3095eb6b431eb.tar.gz
Sqlite: Transaction catch exception in destructor
Fixes coverity warning. We want to throw an exception in the destructor in this case, which is save because it is a RAII pattern and holds only trivial values. Actually this is the only way to communicate that rollback was failing. It is quite rare that it will be happen without an exception is already thrown. There is a non throwing variant too if you want to use it as a class member. Change-Id: Ie71ead19678619465c6ad9334d36ee666225dce7 Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
Diffstat (limited to 'src/libs/sqlite')
-rw-r--r--src/libs/sqlite/sqlitetransaction.h77
1 files changed, 62 insertions, 15 deletions
diff --git a/src/libs/sqlite/sqlitetransaction.h b/src/libs/sqlite/sqlitetransaction.h
index 4fe80d27ec..c58519eb7d 100644
--- a/src/libs/sqlite/sqlitetransaction.h
+++ b/src/libs/sqlite/sqlitetransaction.h
@@ -27,6 +27,7 @@
#include "sqliteglobal.h"
+#include <exception>
#include <mutex>
namespace Sqlite {
@@ -52,12 +53,6 @@ public:
class AbstractTransaction
{
public:
- ~AbstractTransaction()
- {
- if (!m_isAlreadyCommited)
- m_interface.rollback();
- }
-
AbstractTransaction(const AbstractTransaction &) = delete;
AbstractTransaction &operator=(const AbstractTransaction &) = delete;
@@ -73,39 +68,91 @@ protected:
{
}
-private:
+protected:
TransactionInterface &m_interface;
bool m_isAlreadyCommited = false;
};
-class DeferredTransaction final : public AbstractTransaction
+class AbstractThrowingTransaction : public AbstractTransaction
{
public:
- DeferredTransaction(TransactionInterface &interface)
+ ~AbstractThrowingTransaction() noexcept(false)
+ {
+ try {
+ if (!m_isAlreadyCommited)
+ m_interface.rollback();
+ } catch (...) {
+ if (!std::uncaught_exception())
+ throw;
+ }
+ }
+
+protected:
+ AbstractThrowingTransaction(TransactionInterface &interface)
: AbstractTransaction(interface)
{
- interface.deferredBegin();
}
};
-class ImmediateTransaction final : public AbstractTransaction
+class AbstractNonThrowingDestructorTransaction : public AbstractTransaction
{
public:
- ImmediateTransaction(TransactionInterface &interface)
+ ~AbstractNonThrowingDestructorTransaction()
+ {
+ try {
+ if (!m_isAlreadyCommited)
+ m_interface.rollback();
+ } catch (...) {
+ }
+ }
+
+protected:
+ AbstractNonThrowingDestructorTransaction(TransactionInterface &interface)
: AbstractTransaction(interface)
{
+ }
+};
+
+template <typename BaseTransaction>
+class BasicDeferredTransaction final : public BaseTransaction
+{
+public:
+ BasicDeferredTransaction(TransactionInterface &interface)
+ : BaseTransaction(interface)
+ {
+ interface.deferredBegin();
+ }
+};
+
+using DeferredTransaction = BasicDeferredTransaction<AbstractThrowingTransaction>;
+using DeferredNonThrowingDestructorTransaction = BasicDeferredTransaction<AbstractNonThrowingDestructorTransaction>;
+
+template <typename BaseTransaction>
+class BasicImmediateTransaction final : public BaseTransaction
+{
+public:
+ BasicImmediateTransaction(TransactionInterface &interface)
+ : BaseTransaction(interface)
+ {
interface.immediateBegin();
}
};
-class ExclusiveTransaction final : public AbstractTransaction
+using ImmediateTransaction = BasicImmediateTransaction<AbstractThrowingTransaction>;
+using ImmediateNonThrowingDestructorTransaction = BasicImmediateTransaction<AbstractNonThrowingDestructorTransaction>;
+
+template <typename BaseTransaction>
+class BasicExclusiveTransaction final : public BaseTransaction
{
public:
- ExclusiveTransaction(TransactionInterface &interface)
- : AbstractTransaction(interface)
+ BasicExclusiveTransaction(TransactionInterface &interface)
+ : BaseTransaction(interface)
{
interface.exclusiveBegin();
}
};
+using ExclusiveTransaction = BasicExclusiveTransaction<AbstractThrowingTransaction>;
+using ExclusiveNonThrowingDestructorTransaction = BasicExclusiveTransaction<AbstractNonThrowingDestructorTransaction>;
+
} // namespace Sqlite