summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2022-03-06 17:53:23 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2022-03-06 17:53:23 +0000
commit5055c6bcd571dedfb2f129b8b775980eb08b792c (patch)
tree0a6245122164088909f1207d651f24361b7d90d6
parentPush basic database operations into a base class (diff)
downloadicetray-5055c6bcd571dedfb2f129b8b775980eb08b792c.tar.bz2
icetray-5055c6bcd571dedfb2f129b8b775980eb08b792c.tar.xz
icetray-5055c6bcd571dedfb2f129b8b775980eb08b792c.zip
Add helper class for working within a transaction with DB clientsicetray-0.5
-rw-r--r--icetray/icetray/abstractDatabaseClient.cpp9
-rw-r--r--icetray/icetray/abstractDatabaseClient.h6
-rw-r--r--icetray/icetray/transactionalDatabaseClient.cpp7
-rw-r--r--icetray/icetray/transactionalDatabaseClient.h74
-rw-r--r--icetray/unittests/testIceTray.cpp34
-rw-r--r--icetray/unittests/testIceTrayServiceI.cpp3
6 files changed, 132 insertions, 1 deletions
diff --git a/icetray/icetray/abstractDatabaseClient.cpp b/icetray/icetray/abstractDatabaseClient.cpp
index c23d320..bb8a597 100644
--- a/icetray/icetray/abstractDatabaseClient.cpp
+++ b/icetray/icetray/abstractDatabaseClient.cpp
@@ -1,7 +1,16 @@
#include "abstractDatabaseClient.h"
+#include "transactionalDatabaseClient.h"
+#include <connection.h>
#include <connectionPool.h>
#include <utility>
+// IWYU pragma: no_include <map>
namespace IceTray {
AbstractDatabaseClient::AbstractDatabaseClient(DB::ConnectionPoolPtr d) : db(std::move(d)) { }
+
+ TransactionalDatabaseClient<AdHoc::ResourceHandle<DB::Connection>>
+ AbstractDatabaseClient::transactional()
+ {
+ return TransactionalDatabaseClient {db->get()};
+ }
}
diff --git a/icetray/icetray/abstractDatabaseClient.h b/icetray/icetray/abstractDatabaseClient.h
index 5b0807d..98a5eec 100644
--- a/icetray/icetray/abstractDatabaseClient.h
+++ b/icetray/icetray/abstractDatabaseClient.h
@@ -2,12 +2,16 @@
#define ICETRAY_ABSTRACTDATABASECLIENT_H
#include "basicDataClient.h"
+#include "transactionalDatabaseClient.h"
#include <connectionPool.h>
#include <memory>
#include <optional>
#include <string>
#include <visibility.h>
// IWYU pragma: no_include "resourcePool.impl.h"
+namespace DB {
+ class Connection;
+}
namespace IceTray {
class SqlSource;
@@ -42,6 +46,8 @@ namespace IceTray {
return modify(c.get(), sql, params...);
}
+ TransactionalDatabaseClient<AdHoc::ResourceHandle<DB::Connection>> transactional();
+
protected:
DB::ConnectionPoolPtr db;
};
diff --git a/icetray/icetray/transactionalDatabaseClient.cpp b/icetray/icetray/transactionalDatabaseClient.cpp
new file mode 100644
index 0000000..e0376f0
--- /dev/null
+++ b/icetray/icetray/transactionalDatabaseClient.cpp
@@ -0,0 +1,7 @@
+#include "transactionalDatabaseClient.h"
+// IWYU pragma: no_include "resourcePool.impl.h"
+
+namespace IceTray {
+ template class TransactionalDatabaseClient<DB::ConnectionPtr>;
+ template class TransactionalDatabaseClient<AdHoc::ResourceHandle<DB::Connection>>;
+}
diff --git a/icetray/icetray/transactionalDatabaseClient.h b/icetray/icetray/transactionalDatabaseClient.h
new file mode 100644
index 0000000..c496110
--- /dev/null
+++ b/icetray/icetray/transactionalDatabaseClient.h
@@ -0,0 +1,74 @@
+#ifndef ICETRAY_TRANSACTIONALDATABASECLIENT_H
+#define ICETRAY_TRANSACTIONALDATABASECLIENT_H
+
+#include "basicDataClient.h"
+#include "connection.h"
+#include "connection_fwd.h"
+#include <c++11Helpers.h>
+#include <exception>
+#include <memory>
+#include <optional>
+#include <resourcePool.impl.h>
+#include <string>
+#include <utility>
+#include <visibility.h>
+// IWYU pragma: no_include <map>
+
+namespace IceTray {
+ class SqlSource;
+
+ template<typename Connection> class DLL_PUBLIC TransactionalDatabaseClient : public BasicDatabaseClient {
+ public:
+ explicit TransactionalDatabaseClient(Connection db_) : db(std::move(db_))
+ {
+ db->beginTx();
+ }
+
+ virtual ~TransactionalDatabaseClient()
+ {
+ if (std::uncaught_exceptions()) {
+ try {
+ db->rollbackTx();
+ }
+ catch (...) {
+ }
+ }
+ else {
+ db->commitTx();
+ }
+ }
+
+ SPECIAL_MEMBERS_DEFAULT_MOVE_NO_COPY(TransactionalDatabaseClient);
+
+ using BasicDatabaseClient::fetch;
+ using BasicDatabaseClient::modify;
+
+ template<typename Domain, typename... Params>
+ inline Domain
+ fetch(const SqlSource & sql, const Params &... params)
+ {
+ return fetch<Domain, Params...>(std::nullopt, sql, params...);
+ }
+
+ template<typename Domain, typename... Params>
+ inline Domain
+ fetch(const std::optional<std::string> & typeIdCol, const SqlSource & sql, const Params &... params)
+ {
+ return fetch<Domain, Params...>(db.get(), typeIdCol, sql, params...);
+ }
+
+ template<typename... Params>
+ inline auto
+ modify(const SqlSource & sql, const Params &... params)
+ {
+ return modify(db.get(), sql, params...);
+ }
+
+ protected:
+ Connection db;
+ };
+ extern template class TransactionalDatabaseClient<DB::ConnectionPtr>;
+ extern template class TransactionalDatabaseClient<AdHoc::ResourceHandle<DB::Connection>>;
+}
+
+#endif
diff --git a/icetray/unittests/testIceTray.cpp b/icetray/unittests/testIceTray.cpp
index b704864..4a78d03 100644
--- a/icetray/unittests/testIceTray.cpp
+++ b/icetray/unittests/testIceTray.cpp
@@ -1,10 +1,15 @@
#define BOOST_TEST_MODULE TestIceTray
#include <boost/test/unit_test.hpp>
+#include "mockPool.h"
+#include "subdir/some.sql.h"
#include "testIceTrayService.h"
+#include "transactionalDatabaseClient.h"
+#include <Ice/Initialize.h>
#include <Ice/Proxy.h>
#include <definedDirs.h>
#include <dryice.h>
+#include <exception>
#include <filesystem>
#include <icecube.h>
#include <icetrayService.h>
@@ -12,7 +17,9 @@
#include <mockDatabase.h>
#include <pq-mock.h>
#include <staticSqlSource.h>
+#include <string>
#include <testIceTrayServiceTestSql.sql.h>
+// IWYU pragma: no_include "resourcePool.impl.h"
class Service : public IceTray::DryIce, DB::PluginMock<PQ::Mock> {
public:
@@ -73,3 +80,30 @@ BOOST_AUTO_TEST_CASE(sqlModify)
BOOST_REQUIRE(db);
BOOST_REQUIRE(TestIceTray::sql::testIceTrayServiceTestSql.modify(db.get()));
}
+
+struct TxMockPool : public IceTray::MockPool {
+ TxMockPool() : MockPool {"icetraydb", std::string {}, Ice::createProperties()} { }
+};
+
+BOOST_AUTO_TEST_CASE(transactional)
+{
+ TxMockPool pool;
+ IceTray::TransactionalDatabaseClient tdbc {pool.get()};
+ tdbc.fetch<int>(TestIceTray::sql::subdir::some);
+ tdbc.modify(TestIceTray::sql::testIceTrayServiceTestSql, 1, 2);
+}
+
+BOOST_AUTO_TEST_CASE(transactional_rollback)
+{
+ class OnlyThis : public std::exception {
+ };
+ BOOST_CHECK_THROW(
+ {
+ TxMockPool pool;
+ IceTray::TransactionalDatabaseClient tdbc {pool.get()};
+ tdbc.fetch<int>(TestIceTray::sql::subdir::some);
+ tdbc.modify(TestIceTray::sql::testIceTrayServiceTestSql, 1, 2);
+ throw OnlyThis {};
+ },
+ OnlyThis);
+}
diff --git a/icetray/unittests/testIceTrayServiceI.cpp b/icetray/unittests/testIceTrayServiceI.cpp
index 44ef966..7be1599 100644
--- a/icetray/unittests/testIceTrayServiceI.cpp
+++ b/icetray/unittests/testIceTrayServiceI.cpp
@@ -2,6 +2,7 @@
#include "basicDataClient.h"
#include "icecube.h"
#include "testIceTrayService.h"
+#include "transactionalDatabaseClient.h"
#include <Ice/Communicator.h>
#include <Ice/ObjectAdapter.h>
#include <Ice/Optional.h>
@@ -93,7 +94,7 @@ namespace TestIceTray {
Ice::Int
TestIceTrayServiceI::method3(const Ice::Current &)
{
- return static_cast<Ice::Int>(modify(sql::testIceTrayServiceTestSqlUpdate, 5));
+ return static_cast<Ice::Int>(transactional().modify(sql::testIceTrayServiceTestSqlUpdate, 5));
}
void