summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2015-12-29 02:12:20 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2015-12-29 06:00:07 +0000
commit49129dc36008682f5f105e576af279ba84b7b5e1 (patch)
treed9b6b287af7ab79a57523150f66c23d8b9e32780
parentRemove rebind (diff)
downloadlibdbpp-49129dc36008682f5f105e576af279ba84b7b5e1.tar.bz2
libdbpp-49129dc36008682f5f105e576af279ba84b7b5e1.tar.xz
libdbpp-49129dc36008682f5f105e576af279ba84b7b5e1.zip
Add scope transaction helper
-rw-r--r--libdbpp/connection.cpp16
-rw-r--r--libdbpp/connection.h14
-rw-r--r--libdbpp/unittests/testConnection.cpp30
3 files changed, 55 insertions, 5 deletions
diff --git a/libdbpp/connection.cpp b/libdbpp/connection.cpp
index 333becb..1624ce6 100644
--- a/libdbpp/connection.cpp
+++ b/libdbpp/connection.cpp
@@ -74,6 +74,22 @@ DB::TransactionRequired::TransactionRequired() :
{
}
+DB::TransactionScope::TransactionScope(DB::Connection * c) :
+ conn(c)
+{
+ conn->beginTx();
+}
+
+DB::TransactionScope::~TransactionScope()
+{
+ if (std::uncaught_exception()) {
+ conn->rollbackTx();
+ }
+ else {
+ conn->commitTx();
+ }
+}
+
INSTANTIATEFACTORY(DB::Connection, std::string);
PLUGINRESOLVER(DB::ConnectionFactory, DB::Connection::resolvePlugin);
diff --git a/libdbpp/connection.h b/libdbpp/connection.h
index a15a9ab..e34315a 100644
--- a/libdbpp/connection.h
+++ b/libdbpp/connection.h
@@ -133,6 +133,20 @@ namespace DB {
private:
};
+ /// Helper class for beginning/committing/rolling back transactions in accordance with scope and exceptions.
+ class DLL_PUBLIC TransactionScope {
+ public:
+ /// Create a new helper and associated transaction on the given connection.
+ TransactionScope(DB::Connection *);
+ ~TransactionScope();
+
+ private:
+ TransactionScope(const TransactionScope &) = delete;
+ void operator=(const TransactionScope &) = delete;
+
+ Connection * conn;
+ };
+
typedef boost::shared_ptr<Connection> ConnectionPtr;
typedef AdHoc::Factory<Connection, std::string> ConnectionFactory;
}
diff --git a/libdbpp/unittests/testConnection.cpp b/libdbpp/unittests/testConnection.cpp
index 159e5a2..76758a7 100644
--- a/libdbpp/unittests/testConnection.cpp
+++ b/libdbpp/unittests/testConnection.cpp
@@ -12,13 +12,13 @@
// LCOV_EXCL_START
class MockDb : public DB::Connection {
public:
- MockDb(const std::string &) {}
+ MockDb(const std::string &) : txDepth(0) {}
void finish() const {}
- int beginTx() const { return 0; }
- int commitTx() const { return 0; }
- int rollbackTx() const { return 0; }
- bool inTx() const { return false; }
+ int beginTx() const { return ++txDepth; }
+ int commitTx() const { return --txDepth; }
+ int rollbackTx() const { return --txDepth; }
+ bool inTx() const { return txDepth > 0; }
void ping() const {}
DB::BulkDeleteStyle bulkDeleteStyle() const { return DB::BulkDeleteUsingUsing; }
DB::BulkUpdateStyle bulkUpdateStyle() const { return DB::BulkUpdateUsingJoin; }
@@ -34,6 +34,7 @@ class MockDb : public DB::Connection {
size_t bulkUploadData(const char *, size_t) const {return 0;}
mutable std::vector<std::string> executed;
+ mutable unsigned int txDepth;
};
// LCOV_EXCL_STOP
@@ -126,6 +127,25 @@ BOOST_AUTO_TEST_CASE( parse2 )
s.close();
}
+BOOST_AUTO_TEST_CASE( txscope )
+{
+ auto mock = DB::ConnectionFactory::createNew("MockDb", "doesn't matter");
+ BOOST_REQUIRE(mock);
+ BOOST_REQUIRE_EQUAL(false, mock->inTx());
+ {
+ DB::TransactionScope tx(mock);
+ BOOST_REQUIRE_EQUAL(true, mock->inTx());
+ }
+ BOOST_REQUIRE_EQUAL(false, mock->inTx());
+ try {
+ DB::TransactionScope tx(mock);
+ BOOST_REQUIRE_EQUAL(true, mock->inTx());
+ throw std::exception();
+ }
+ catch (...) {
+ BOOST_REQUIRE_EQUAL(false, mock->inTx());
+ }
+}
BOOST_AUTO_TEST_CASE( savepoints )
{