From f2ea61052e40b46e0e9da60147d43ee0bd46f551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20A=C3=9Fmann?= Date: Tue, 30 May 2017 00:17:08 +0200 Subject: [PATCH] Add an option to set a transaction isolation level to the generic transaction interface and the connecctor api --- connector_api/connection.h | 3 ++- include/sqlpp11/transaction.h | 31 +++++++++++++++++++++++++++++-- tests/MockDb.h | 17 +++++++++++++++++ tests/Select.cpp | 3 +++ 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/connector_api/connection.h b/connector_api/connection.h index dc2f81c2..440704ac 100644 --- a/connector_api/connection.h +++ b/connector_api/connection.h @@ -29,6 +29,7 @@ #include #include +#include #include // You may use char result or bind result or both #include // to represent results of select and prepared select @@ -130,7 +131,7 @@ namespace sqlpp } //! start transaction - void start_transaction(); + void start_transaction(isolation_level isolation = isolation_level::undefined); //! commit transaction (or throw transaction if the transaction has been finished already) void commit_transaction(); diff --git a/include/sqlpp11/transaction.h b/include/sqlpp11/transaction.h index 130a664b..317c3483 100644 --- a/include/sqlpp11/transaction.h +++ b/include/sqlpp11/transaction.h @@ -34,6 +34,14 @@ namespace sqlpp static constexpr bool quiet_auto_rollback = false; static constexpr bool report_auto_rollback = true; + enum class isolation_level { + undefined, // use the current database default + serializable, // highest level, stronguest guarantee + repeatable_read, // DBMS holds read and write locks + read_committed, // DMBS holds read locks, non-repeatable reads can occur + read_uncommitted // lowest isolation level, dirty reads may occur + }; + template class transaction_t { @@ -48,6 +56,12 @@ namespace sqlpp _db.start_transaction(); } + transaction_t(Db& db, bool report_unfinished_transaction, isolation_level isolation) + : _db(db), _report_unfinished_transaction(report_unfinished_transaction) + { + _db.start_transaction(isolation); + } + transaction_t(const transaction_t&) = delete; transaction_t(transaction_t&&) = default; transaction_t& operator=(const transaction_t&) = delete; @@ -86,9 +100,22 @@ namespace sqlpp }; template - transaction_t start_transaction(Db& db, bool report_unfinished_transaction = report_auto_rollback) + transaction_t start_transaction(Db& db, bool report_unfinished_transaction) { - return {db, report_unfinished_transaction}; + return {db, report_unfinished_transaction}; + } + + template + transaction_t start_transaction(Db& db, bool report_unfinished_transaction = report_auto_rollback, + isolation_level isolation = isolation_level::undefined) + { + return {db, report_unfinished_transaction, isolation}; + } + + template + transaction_t start_transaction(Db& db, isolation_level isolation, bool report_unfinished_transaction = report_auto_rollback) + { + return {db, report_unfinished_transaction, isolation}; } } diff --git a/tests/MockDb.h b/tests/MockDb.h index 6e9dece4..1da2d555 100644 --- a/tests/MockDb.h +++ b/tests/MockDb.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -244,6 +245,22 @@ struct MockDbT : public sqlpp::connection { return {name}; } + + void start_transaction(sqlpp::isolation_level level) + { + _current_isolation_level = level; + } + + void rollback_transaction(bool) + {} + + void commit_transaction() + {} + + void report_rollback_failure(std::string) + {} + + sqlpp::isolation_level _current_isolation_level; }; using MockDb = MockDbT; diff --git a/tests/Select.cpp b/tests/Select.cpp index 268488f2..da5a63eb 100644 --- a/tests/Select.cpp +++ b/tests/Select.cpp @@ -183,5 +183,8 @@ int Select(int, char* []) for_each_field(row, to_cerr{}); } + auto transaction = start_transaction(db, sqlpp::report_auto_rollback, sqlpp::isolation_level::read_committed); + std::cout << (db._current_isolation_level == sqlpp::isolation_level::read_committed) << std::endl; + return 0; }