mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-17 19:25:53 +02:00
more callbacks and transaction tests
- added callbacks for commit and rollback with tests - added transaction tests
This commit is contained in:
@@ -141,7 +141,7 @@ public:
|
||||
SessionHandle& handle();
|
||||
// Get handle
|
||||
|
||||
const std::string& connectorName();
|
||||
const std::string& connectorName() const;
|
||||
/// Returns the name of the connector.
|
||||
|
||||
private:
|
||||
@@ -208,7 +208,7 @@ inline SessionHandle& SessionImpl::handle()
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& SessionImpl::connectorName()
|
||||
inline const std::string& SessionImpl::connectorName() const
|
||||
{
|
||||
return _connector;
|
||||
}
|
||||
|
@@ -122,7 +122,7 @@ public:
|
||||
bool isTransaction();
|
||||
/// Returns true iff a transaction is in progress.
|
||||
|
||||
const std::string& connectorName();
|
||||
const std::string& connectorName() const;
|
||||
/// Returns the name of the connector.
|
||||
|
||||
bool canTransact();
|
||||
@@ -263,7 +263,7 @@ inline bool SessionImpl::isAutoExtract(const std::string& name)
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& SessionImpl::connectorName()
|
||||
inline const std::string& SessionImpl::connectorName() const
|
||||
{
|
||||
return _connector;
|
||||
}
|
||||
|
@@ -52,6 +52,9 @@ struct sqlite3_stmt;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
class Mutex;
|
||||
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
@@ -125,7 +128,13 @@ public:
|
||||
/// Returns true iff the transaction isolation level corresponds
|
||||
/// to the supplied bitmask.
|
||||
|
||||
const std::string& connectorName();
|
||||
void autoCommit(const std::string&, bool val);
|
||||
/// Sets autocommit property for the session.
|
||||
|
||||
bool isAutoCommit(const std::string& name="");
|
||||
/// Returns autocommit property value.
|
||||
|
||||
const std::string& connectorName() const;
|
||||
/// Returns the name of the connector.
|
||||
|
||||
private:
|
||||
@@ -134,7 +143,7 @@ private:
|
||||
bool _connected;
|
||||
bool _isTransaction;
|
||||
int _timeout;
|
||||
|
||||
Mutex _mutex;
|
||||
static const std::string DEFERRED_BEGIN_TRANSACTION;
|
||||
static const std::string COMMIT_TRANSACTION;
|
||||
static const std::string ABORT_TRANSACTION;
|
||||
@@ -156,7 +165,7 @@ inline bool SessionImpl::isTransaction()
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& SessionImpl::connectorName()
|
||||
inline const std::string& SessionImpl::connectorName() const
|
||||
{
|
||||
return _connector;
|
||||
}
|
||||
|
@@ -42,6 +42,7 @@
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
#include "Poco/Data/MetaColumn.h"
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/Types.h"
|
||||
#include <map>
|
||||
@@ -57,7 +58,7 @@ namespace SQLite {
|
||||
|
||||
|
||||
class SQLite_API Utility
|
||||
/// Various utility functions for SQLite, mostly return code handling
|
||||
/// Various utility functions for SQLite.
|
||||
{
|
||||
public:
|
||||
static const std::string SQLITE_DATE_FORMAT;
|
||||
@@ -72,8 +73,14 @@ public:
|
||||
static const int OPERATION_DELETE;
|
||||
static const int OPERATION_UPDATE;
|
||||
|
||||
static sqlite3* dbHandle(const Session& session);
|
||||
/// Returns native DB handle.
|
||||
|
||||
static std::string lastError(sqlite3* pDb);
|
||||
/// Retreives the last error code from sqlite and converts it to a string
|
||||
/// Retreives the last error code from sqlite and converts it to a string.
|
||||
|
||||
static std::string lastError(const Session& session);
|
||||
/// Retreives the last error code from sqlite and converts it to a string.
|
||||
|
||||
static void throwException(int rc, const std::string& addErrMsg = std::string());
|
||||
/// Throws for an error code the appropriate exception
|
||||
@@ -85,13 +92,25 @@ public:
|
||||
/// Loads the contents of a database file on disk into an opened
|
||||
/// database in memory.
|
||||
///
|
||||
/// Returns true if succesful
|
||||
/// Returns true if succesful.
|
||||
|
||||
static bool fileToMemory(const Session& session, const std::string& fileName);
|
||||
/// Loads the contents of a database file on disk into an opened
|
||||
/// database in memory.
|
||||
///
|
||||
/// Returns true if succesful.
|
||||
|
||||
static bool memoryToFile(const std::string& fileName, sqlite3* pInMemory);
|
||||
/// Saves the contents of an opened database in memory to the
|
||||
/// database on disk.
|
||||
///
|
||||
/// Returns true if succesful
|
||||
/// Returns true if succesful.
|
||||
|
||||
static bool memoryToFile(const std::string& fileName, const Session& session);
|
||||
/// Saves the contents of an opened database in memory to the
|
||||
/// database on disk.
|
||||
///
|
||||
/// Returns true if succesful.
|
||||
|
||||
static bool isThreadSafe();
|
||||
/// Returns true if SQLite was compiled in multi-thread or serialized mode.
|
||||
@@ -121,27 +140,57 @@ public:
|
||||
static bool registerUpdateHandler(sqlite3* pDB, CBT callbackFn, T* pParam)
|
||||
/// Registers the callback for (1)(insert, delete, update), (2)(commit) or
|
||||
/// or (3)(rollback) events. Only one function per group can be registered
|
||||
/// at a time. Registration is thread-safe. Storage pointed to by pParam
|
||||
/// at a time. Registration is not thread-safe. Storage pointed to by pParam
|
||||
/// must remain valid as long as registration is active. Registering with
|
||||
/// callbackFn set to zero disables notifications.
|
||||
///
|
||||
/// See http://www.sqlite.org/c3ref/update_hook.html and
|
||||
/// http://www.sqlite.org/c3ref/commit_hook.html for details.
|
||||
{
|
||||
typedef std::map<sqlite3*, T*> RetMap;
|
||||
typedef std::pair<typename CBT, T*> CBPair;
|
||||
typedef std::multimap<sqlite3*, CBPair> CBMap;
|
||||
typedef CBMap::iterator CBMapIt;
|
||||
typedef std::pair<CBMapIt, CBMapIt> CBMapItPair;
|
||||
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
static RetMap retMap;
|
||||
T* pRet = reinterpret_cast<T*>(eventHook(pDB, callbackFn, pParam));
|
||||
static CBMap retMap;
|
||||
T* pRet = reinterpret_cast<T*>(eventHookRegister(pDB, callbackFn, pParam));
|
||||
|
||||
bool success = false;
|
||||
if (pRet == 0)
|
||||
{
|
||||
if (retMap.find(pDB) == retMap.end())
|
||||
success = (pRet == 0);
|
||||
else if (pRet != 0)
|
||||
success = (*pRet == *retMap[pDB]);
|
||||
{
|
||||
retMap.insert(CBMap::value_type(pDB, CBPair(callbackFn, pParam)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CBMapItPair retMapRange = retMap.equal_range(pDB);
|
||||
for (CBMapIt it = retMapRange.first; it != retMapRange.second; ++it)
|
||||
{
|
||||
poco_assert (it->second.first != 0);
|
||||
if ((callbackFn == 0) && (*pRet == *it->second.second))
|
||||
{
|
||||
retMap.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (success) retMap[pDB] = pParam;
|
||||
return success;
|
||||
if ((callbackFn == it->second.first) && (*pRet == *it->second.second))
|
||||
{
|
||||
it->second.second = pParam;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T, typename CBT>
|
||||
static bool registerUpdateHandler(const Session& session, CBT callbackFn, T* pParam)
|
||||
/// Registers the callback by calling registerUpdateHandler(sqlite3*, CBT, T*).
|
||||
{
|
||||
return registerUpdateHandler(dbHandle(session), callbackFn, pParam);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -158,9 +207,9 @@ private:
|
||||
Utility(const Utility&);
|
||||
Utility& operator = (const Utility&);
|
||||
|
||||
static void* eventHook(sqlite3* pDB, UpdateCallbackType callbackFn, void* pParam);
|
||||
static void* eventHook(sqlite3* pDB, CommitCallbackType callbackFn, void* pParam);
|
||||
static void* eventHook(sqlite3* pDB, RollbackCallbackType callbackFn, void* pParam);
|
||||
static void* eventHookRegister(sqlite3* pDB, UpdateCallbackType callbackFn, void* pParam);
|
||||
static void* eventHookRegister(sqlite3* pDB, CommitCallbackType callbackFn, void* pParam);
|
||||
static void* eventHookRegister(sqlite3* pDB, RollbackCallbackType callbackFn, void* pParam);
|
||||
|
||||
static TypeMap _types;
|
||||
static Poco::Mutex _mutex;
|
||||
@@ -168,7 +217,38 @@ private:
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline sqlite3* Utility::dbHandle(const Session& session)
|
||||
{
|
||||
return AnyCast<sqlite3*>(session.getProperty("handle"));
|
||||
}
|
||||
|
||||
|
||||
inline std::string Utility::lastError(const Session& session)
|
||||
{
|
||||
poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
|
||||
return lastError(dbHandle(session));
|
||||
}
|
||||
|
||||
|
||||
inline bool Utility::memoryToFile(const std::string& fileName, const Session& session)
|
||||
{
|
||||
poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
|
||||
return memoryToFile(fileName, dbHandle(session));
|
||||
}
|
||||
|
||||
|
||||
inline bool Utility::fileToMemory(const Session& session, const std::string& fileName)
|
||||
{
|
||||
poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
|
||||
return fileToMemory(dbHandle(session), fileName);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif
|
||||
#endif // SQLite_Utility_INCLUDED
|
||||
|
@@ -42,6 +42,7 @@
|
||||
#include "Poco/ActiveMethod.h"
|
||||
#include "Poco/ActiveResult.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/Data/DataException.h"
|
||||
#include "sqlite3.h"
|
||||
#include <cstdlib>
|
||||
@@ -67,6 +68,9 @@ SessionImpl::SessionImpl(const std::string& fileName, std::size_t loginTimeout):
|
||||
open();
|
||||
setConnectionTimeout(CONNECTION_TIMEOUT_DEFAULT);
|
||||
setProperty("handle", _pDB);
|
||||
addFeature("autoCommit",
|
||||
&SessionImpl::autoCommit,
|
||||
&SessionImpl::isAutoCommit);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +89,7 @@ Poco::Data::StatementImpl* SessionImpl::createStatementImpl()
|
||||
|
||||
void SessionImpl::begin()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
SQLiteStatementImpl tmp(*this, _pDB);
|
||||
tmp.add(DEFERRED_BEGIN_TRANSACTION);
|
||||
tmp.execute();
|
||||
@@ -94,6 +99,7 @@ void SessionImpl::begin()
|
||||
|
||||
void SessionImpl::commit()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
SQLiteStatementImpl tmp(*this, _pDB);
|
||||
tmp.add(COMMIT_TRANSACTION);
|
||||
tmp.execute();
|
||||
@@ -103,6 +109,7 @@ void SessionImpl::commit()
|
||||
|
||||
void SessionImpl::rollback()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
SQLiteStatementImpl tmp(*this, _pDB);
|
||||
tmp.add(ABORT_TRANSACTION);
|
||||
tmp.execute();
|
||||
@@ -233,4 +240,21 @@ void SessionImpl::setConnectionTimeout(std::size_t timeout)
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::autoCommit(const std::string&, bool)
|
||||
{
|
||||
// The problem here is to decide whether to call commit or rollback
|
||||
// when autocommit is set to true. Hence, it is best not to implement
|
||||
// this explicit call and only implicitly support autocommit setting.
|
||||
throw NotImplementedException(
|
||||
"SQLite autocommit is implicit with begin/commit/rollback.");
|
||||
}
|
||||
|
||||
|
||||
bool SessionImpl::isAutoCommit(const std::string&)
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
return (0 != sqlite3_get_autocommit(_pDB));
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
@@ -40,6 +40,7 @@
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/Exception.h"
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <sqlite3.h>
|
||||
@@ -133,7 +134,7 @@ Utility::Utility()
|
||||
}
|
||||
|
||||
|
||||
std::string Utility::lastError(sqlite3 *pDB)
|
||||
std::string Utility::lastError(sqlite3* pDB)
|
||||
{
|
||||
return std::string(sqlite3_errmsg(pDB));
|
||||
}
|
||||
@@ -220,7 +221,7 @@ void Utility::throwException(int rc, const std::string& addErrMsg)
|
||||
case SQLITE_DONE:
|
||||
break; // sqlite_step() has finished executing
|
||||
default:
|
||||
throw SQLiteException(std::string("Unkown error code: ") + Poco::NumberFormatter::format(rc), addErrMsg);
|
||||
throw SQLiteException(std::string("Unknown error code: ") + Poco::NumberFormatter::format(rc), addErrMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,20 +304,20 @@ bool Utility::setThreadMode(int mode)
|
||||
}
|
||||
|
||||
|
||||
void* Utility::eventHook(sqlite3* pDB, UpdateCallbackType callbackFn, void* pParam)
|
||||
void* Utility::eventHookRegister(sqlite3* pDB, UpdateCallbackType callbackFn, void* pParam)
|
||||
{
|
||||
typedef void(*pF)(void*, int, const char*, const char*, sqlite3_int64);
|
||||
return sqlite3_update_hook(pDB, reinterpret_cast<pF>(callbackFn), pParam);
|
||||
}
|
||||
|
||||
|
||||
void* Utility::eventHook(sqlite3* pDB, CommitCallbackType callbackFn, void* pParam)
|
||||
void* Utility::eventHookRegister(sqlite3* pDB, CommitCallbackType callbackFn, void* pParam)
|
||||
{
|
||||
return sqlite3_commit_hook(pDB, callbackFn, pParam);
|
||||
}
|
||||
|
||||
|
||||
void* Utility::eventHook(sqlite3* pDB, RollbackCallbackType callbackFn, void* pParam)
|
||||
void* Utility::eventHookRegister(sqlite3* pDB, RollbackCallbackType callbackFn, void* pParam)
|
||||
{
|
||||
return sqlite3_rollback_hook(pDB, callbackFn, pParam);
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@
|
||||
#include "Poco/Dynamic/Var.h"
|
||||
#include "Poco/Data/TypeHandler.h"
|
||||
#include "Poco/Nullable.h"
|
||||
#include "Poco/Data/Transaction.h"
|
||||
#include "Poco/Data/DataException.h"
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
#include "Poco/Tuple.h"
|
||||
@@ -73,6 +74,7 @@ using Poco::Data::LimitException;
|
||||
using Poco::Data::CLOB;
|
||||
using Poco::Data::Date;
|
||||
using Poco::Data::Time;
|
||||
using Poco::Data::Transaction;
|
||||
using Poco::Data::AbstractExtractionVec;
|
||||
using Poco::Data::AbstractExtractionVecVec;
|
||||
using Poco::Data::AbstractBindingVec;
|
||||
@@ -87,11 +89,14 @@ using Poco::Logger;
|
||||
using Poco::Message;
|
||||
using Poco::AutoPtr;
|
||||
using Poco::Thread;
|
||||
using Poco::format;
|
||||
using Poco::InvalidAccessException;
|
||||
using Poco::RangeException;
|
||||
using Poco::BadCastException;
|
||||
using Poco::NotFoundException;
|
||||
using Poco::NullPointerException;
|
||||
using Poco::TimeoutException;
|
||||
using Poco::NotImplementedException;
|
||||
using Poco::Data::SQLite::ConstraintViolationException;
|
||||
using Poco::Data::SQLite::ParameterCountMismatchException;
|
||||
using Poco::Int32;
|
||||
@@ -362,9 +367,7 @@ void SQLiteTest::testInMemory()
|
||||
|
||||
// load db from file to memory
|
||||
Session mem (Poco::Data::SQLite::Connector::KEY, ":memory:");
|
||||
sqlite3* p = 0; Any a = p; // ??? clang generated code fails to AnyCast without these
|
||||
sqlite3* pMemHandle = AnyCast<sqlite3*>(mem.getProperty("handle"));
|
||||
assert (Poco::Data::SQLite::Utility::fileToMemory(pMemHandle, "dummy.db"));
|
||||
assert (Poco::Data::SQLite::Utility::fileToMemory(mem, "dummy.db"));
|
||||
|
||||
mem << "SELECT COUNT(*) FROM PERSON", into(count), now;
|
||||
assert (count == 1);
|
||||
@@ -378,7 +381,7 @@ void SQLiteTest::testInMemory()
|
||||
|
||||
// save db from memory to file on the disk
|
||||
Session dsk (Poco::Data::SQLite::Connector::KEY, "dsk.db");
|
||||
assert (Poco::Data::SQLite::Utility::memoryToFile("dsk.db", pMemHandle));
|
||||
assert (Poco::Data::SQLite::Utility::memoryToFile("dsk.db", mem));
|
||||
|
||||
dsk << "SELECT COUNT(*) FROM PERSON", into(count), now;
|
||||
assert (count == 1);
|
||||
@@ -2661,29 +2664,29 @@ void SQLiteTest::testThreadModes()
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::sqliteUpdateCallbackFn(void* pVal, int opCode, const char* pDB, const char* pTable, Poco::Int64 val)
|
||||
void SQLiteTest::sqliteUpdateCallbackFn(void* pVal, int opCode, const char* pDB, const char* pTable, Poco::Int64 row)
|
||||
{
|
||||
poco_check_ptr(pVal);
|
||||
Poco::Int64* pV = reinterpret_cast<Poco::Int64*>(pVal);
|
||||
if (opCode == Utility::OPERATION_INSERT)
|
||||
{
|
||||
poco_assert (*pV == 2);
|
||||
poco_assert (val == 1);
|
||||
std::cout << "Inserted " << pDB << '.' << pTable << ", RowID=" << val << std::endl;
|
||||
poco_assert (row == 1);
|
||||
std::cout << "Inserted " << pDB << '.' << pTable << ", RowID=" << row << std::endl;
|
||||
++_insertCounter;
|
||||
}
|
||||
else if (opCode == Utility::OPERATION_UPDATE)
|
||||
{
|
||||
poco_assert (*pV == 3);
|
||||
poco_assert (val == 1);
|
||||
std::cout << "Updated " << pDB << '.' << pTable << ", RowID=" << val << std::endl;
|
||||
poco_assert (row == 1);
|
||||
std::cout << "Updated " << pDB << '.' << pTable << ", RowID=" << row << std::endl;
|
||||
++_updateCounter;
|
||||
}
|
||||
else if (opCode == Utility::OPERATION_DELETE)
|
||||
{
|
||||
poco_assert (*pV == 4);
|
||||
poco_assert (val == 1);
|
||||
std::cout << "Deleted " << pDB << '.' << pTable << ", RowID=" << val << std::endl;
|
||||
poco_assert (row == 1);
|
||||
std::cout << "Deleted " << pDB << '.' << pTable << ", RowID=" << row << std::endl;
|
||||
++_deleteCounter;
|
||||
}
|
||||
}
|
||||
@@ -2698,9 +2701,8 @@ void SQLiteTest::testUpdateCallback()
|
||||
|
||||
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
assert (tmp.isConnected());
|
||||
sqlite3* pDB = AnyCast<sqlite3*>(tmp.getProperty("handle"));
|
||||
Poco::Int64 val = 1;
|
||||
assert (Utility::registerUpdateHandler(pDB, &sqliteUpdateCallbackFn, &val));
|
||||
assert (Utility::registerUpdateHandler(tmp, &sqliteUpdateCallbackFn, &val));
|
||||
|
||||
std::string tableName("Person");
|
||||
std::string lastName("lastname");
|
||||
@@ -2740,7 +2742,7 @@ void SQLiteTest::testUpdateCallback()
|
||||
assert (_deleteCounter == 1);
|
||||
|
||||
// disarm callback and do the same drill
|
||||
assert (Utility::registerUpdateHandler(pDB, (Utility::UpdateCallbackType) 0, &val));
|
||||
assert (Utility::registerUpdateHandler(tmp, (Utility::UpdateCallbackType) 0, &val));
|
||||
|
||||
tmp << "DROP TABLE IF EXISTS Person", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
|
||||
@@ -2779,6 +2781,436 @@ void SQLiteTest::testUpdateCallback()
|
||||
}
|
||||
|
||||
|
||||
int SQLiteTest::sqliteCommitCallbackFn(void* pVal)
|
||||
{
|
||||
poco_check_ptr(pVal);
|
||||
Poco::Int64* pV = reinterpret_cast<Poco::Int64*>(pVal);
|
||||
poco_assert ((*pV) == 1);
|
||||
++(*pV);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testCommitCallback()
|
||||
{
|
||||
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
assert (tmp.isConnected());
|
||||
Poco::Int64 val = 1;
|
||||
assert (Utility::registerUpdateHandler(tmp, &sqliteCommitCallbackFn, &val));
|
||||
|
||||
std::string tableName("Person");
|
||||
std::string lastName("lastname");
|
||||
std::string firstName("firstname");
|
||||
std::string address("Address");
|
||||
int age = 133132;
|
||||
int count = 0;
|
||||
std::string result;
|
||||
tmp.begin();
|
||||
tmp << "DROP TABLE IF EXISTS Person", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
|
||||
tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
|
||||
tmp.commit();
|
||||
assert (val == 2);
|
||||
|
||||
assert (Utility::registerUpdateHandler(tmp, (Utility::CommitCallbackType) 0, &val));
|
||||
val = 0;
|
||||
tmp.begin();
|
||||
tmp << "DROP TABLE IF EXISTS Person", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
|
||||
tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
|
||||
tmp.commit();
|
||||
assert (val == 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::sqliteRollbackCallbackFn(void* pVal)
|
||||
{
|
||||
poco_check_ptr(pVal);
|
||||
Poco::Int64* pV = reinterpret_cast<Poco::Int64*>(pVal);
|
||||
poco_assert ((*pV) == 1);
|
||||
++(*pV);
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testRollbackCallback()
|
||||
{
|
||||
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
assert (tmp.isConnected());
|
||||
Poco::Int64 val = 1;
|
||||
assert (Utility::registerUpdateHandler(tmp, &sqliteRollbackCallbackFn, &val));
|
||||
|
||||
std::string tableName("Person");
|
||||
std::string lastName("lastname");
|
||||
std::string firstName("firstname");
|
||||
std::string address("Address");
|
||||
int age = 133132;
|
||||
int count = 0;
|
||||
std::string result;
|
||||
tmp.begin();
|
||||
tmp << "DROP TABLE IF EXISTS Person", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
|
||||
tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
|
||||
tmp.rollback();
|
||||
assert (val == 2);
|
||||
|
||||
assert (Utility::registerUpdateHandler(tmp, (Utility::RollbackCallbackType) 0, &val));
|
||||
val = 0;
|
||||
tmp.begin();
|
||||
tmp << "DROP TABLE IF EXISTS Person", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
|
||||
tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
|
||||
tmp.rollback();
|
||||
assert (val == 0);
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::setTransactionIsolation(Session& session, Poco::UInt32 ti)
|
||||
{
|
||||
if (session.hasTransactionIsolation(ti))
|
||||
{
|
||||
std::string funct = "setTransactionIsolation()";
|
||||
|
||||
try
|
||||
{
|
||||
Transaction t(session, false);
|
||||
t.setIsolation(ti);
|
||||
|
||||
assert (ti == t.getIsolation());
|
||||
assert (t.isIsolation(ti));
|
||||
|
||||
assert (ti == session.getTransactionIsolation());
|
||||
assert (session.isTransactionIsolation(ti));
|
||||
}
|
||||
catch(Poco::Exception& e){ std::cout << funct << ':' << e.displayText() << std::endl;}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << '[' << name() << ']' << " Warning, transaction isolation not supported: ";
|
||||
switch (ti)
|
||||
{
|
||||
case Session::TRANSACTION_READ_COMMITTED:
|
||||
std::cerr << "READ COMMITTED"; break;
|
||||
case Session::TRANSACTION_READ_UNCOMMITTED:
|
||||
std::cerr << "READ UNCOMMITTED"; break;
|
||||
case Session::TRANSACTION_REPEATABLE_READ:
|
||||
std::cerr << "REPEATABLE READ"; break;
|
||||
case Session::TRANSACTION_SERIALIZABLE:
|
||||
std::cerr << "SERIALIZABLE"; break;
|
||||
default:
|
||||
std::cerr << "UNKNOWN"; break;
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testSessionTransaction()
|
||||
{
|
||||
Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
assert (session.isConnected());
|
||||
|
||||
session << "DROP TABLE IF EXISTS Person", now;
|
||||
session << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
|
||||
|
||||
if (!session.canTransact())
|
||||
{
|
||||
std::cout << "Session not capable of transactions." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
Session local (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
assert (local.isConnected());
|
||||
|
||||
try
|
||||
{
|
||||
local.setFeature("autoCommit", true);
|
||||
fail ("Setting SQLite auto-commit explicitly must fail!");
|
||||
}
|
||||
catch (NotImplementedException&) { }
|
||||
assert (local.getFeature("autoCommit"));
|
||||
|
||||
std::string funct = "transaction()";
|
||||
std::vector<std::string> lastNames;
|
||||
std::vector<std::string> firstNames;
|
||||
std::vector<std::string> addresses;
|
||||
std::vector<int> ages;
|
||||
std::string tableName("Person");
|
||||
lastNames.push_back("LN1");
|
||||
lastNames.push_back("LN2");
|
||||
firstNames.push_back("FN1");
|
||||
firstNames.push_back("FN2");
|
||||
addresses.push_back("ADDR1");
|
||||
addresses.push_back("ADDR2");
|
||||
ages.push_back(1);
|
||||
ages.push_back(2);
|
||||
int count = 0, locCount = 0;
|
||||
std::string result;
|
||||
|
||||
setTransactionIsolation(session, Session::TRANSACTION_READ_COMMITTED);
|
||||
|
||||
session.begin();
|
||||
assert (!session.getFeature("autoCommit"));
|
||||
assert (session.isTransaction());
|
||||
session << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
|
||||
assert (session.isTransaction());
|
||||
|
||||
Statement stmt = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
|
||||
|
||||
session << "SELECT COUNT(*) FROM Person", into(count), now;
|
||||
assert (2 == count);
|
||||
assert (session.isTransaction());
|
||||
session.rollback();
|
||||
assert (!session.isTransaction());
|
||||
assert (session.getFeature("autoCommit"));
|
||||
|
||||
stmt.wait();
|
||||
assert (0 == locCount);
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (0 == count);
|
||||
assert (!session.isTransaction());
|
||||
|
||||
session.begin();
|
||||
session << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
|
||||
assert (session.isTransaction());
|
||||
assert (!session.getFeature("autoCommit"));
|
||||
|
||||
Statement stmt1 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now);
|
||||
assert (0 == locCount);
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (2 == count);
|
||||
|
||||
session.commit();
|
||||
assert (!session.isTransaction());
|
||||
assert (session.getFeature("autoCommit"));
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (2 == count);
|
||||
|
||||
/* TODO: see http://www.sqlite.org/pragma.html#pragma_read_uncommitted
|
||||
setTransactionIsolation(session, Session::TRANSACTION_READ_UNCOMMITTED);
|
||||
*/
|
||||
|
||||
session.close();
|
||||
assert (!session.isConnected());
|
||||
|
||||
local.close();
|
||||
assert (!local.isConnected());
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testTransaction()
|
||||
{
|
||||
Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
assert (session.isConnected());
|
||||
|
||||
session << "DROP TABLE IF EXISTS Person", now;
|
||||
session << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
|
||||
|
||||
if (!session.canTransact())
|
||||
{
|
||||
std::cout << "Session not transaction-capable." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
Session local(Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
|
||||
setTransactionIsolation(session, Session::TRANSACTION_READ_COMMITTED);
|
||||
|
||||
std::string funct = "transaction()";
|
||||
std::vector<std::string> lastNames;
|
||||
std::vector<std::string> firstNames;
|
||||
std::vector<std::string> addresses;
|
||||
std::vector<int> ages;
|
||||
std::string tableName("Person");
|
||||
lastNames.push_back("LN1");
|
||||
lastNames.push_back("LN2");
|
||||
firstNames.push_back("FN1");
|
||||
firstNames.push_back("FN2");
|
||||
addresses.push_back("ADDR1");
|
||||
addresses.push_back("ADDR2");
|
||||
ages.push_back(1);
|
||||
ages.push_back(2);
|
||||
int count = 0, locCount = 0;
|
||||
std::string result;
|
||||
|
||||
session.setTransactionIsolation(Session::TRANSACTION_READ_COMMITTED);
|
||||
|
||||
{
|
||||
Transaction trans(session);
|
||||
assert (trans.isActive());
|
||||
assert (session.isTransaction());
|
||||
|
||||
session << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
|
||||
|
||||
assert (session.isTransaction());
|
||||
assert (trans.isActive());
|
||||
|
||||
session << "SELECT COUNT(*) FROM Person", into(count), now;
|
||||
assert (2 == count);
|
||||
assert (session.isTransaction());
|
||||
assert (trans.isActive());
|
||||
// no explicit commit, so transaction RAII must roll back here
|
||||
}
|
||||
assert (!session.isTransaction());
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (0 == count);
|
||||
assert (!session.isTransaction());
|
||||
|
||||
{
|
||||
Transaction trans(session);
|
||||
session << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
|
||||
|
||||
Statement stmt1 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now);
|
||||
|
||||
assert (session.isTransaction());
|
||||
assert (trans.isActive());
|
||||
trans.commit();
|
||||
assert (!session.isTransaction());
|
||||
assert (!trans.isActive());
|
||||
assert (0 == locCount);
|
||||
}
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (2 == count);
|
||||
local << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (2 == count);
|
||||
|
||||
session << "DELETE FROM Person", now;
|
||||
|
||||
std::string sql1 = format("INSERT INTO Person VALUES ('%s','%s','%s',%d)", lastNames[0], firstNames[0], addresses[0], ages[0]);
|
||||
std::string sql2 = format("INSERT INTO Person VALUES ('%s','%s','%s',%d)", lastNames[1], firstNames[1], addresses[1], ages[1]);
|
||||
std::vector<std::string> sql;
|
||||
sql.push_back(sql1);
|
||||
sql.push_back(sql2);
|
||||
|
||||
Transaction trans(session);
|
||||
|
||||
trans.execute(sql1, false);
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (1 == count);
|
||||
trans.execute(sql2, false);
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (2 == count);
|
||||
|
||||
Statement stmt2 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now);
|
||||
assert (0 == locCount);
|
||||
|
||||
trans.rollback();
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (0 == count);
|
||||
|
||||
trans.execute(sql);
|
||||
|
||||
Statement stmt3 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now);
|
||||
assert (2 == locCount);
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (2 == count);
|
||||
|
||||
session.close();
|
||||
assert (!session.isConnected());
|
||||
|
||||
local.close();
|
||||
assert (!local.isConnected());
|
||||
}
|
||||
|
||||
|
||||
struct TestCommitTransactor
|
||||
{
|
||||
void operator () (Session& session) const
|
||||
{
|
||||
session << "INSERT INTO Person VALUES ('lastName','firstName','address',10)", now;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct TestRollbackTransactor
|
||||
{
|
||||
void operator () (Session& session) const
|
||||
{
|
||||
session << "INSERT INTO Person VALUES ('lastName','firstName','address',10)", now;
|
||||
throw Poco::Exception("test");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void SQLiteTest::testTransactor()
|
||||
{
|
||||
Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
assert (session.isConnected());
|
||||
|
||||
session << "DROP TABLE IF EXISTS Person", now;
|
||||
session << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
|
||||
|
||||
std::string funct = "transaction()";
|
||||
int count = 0;
|
||||
|
||||
assert (session.getFeature("autoCommit"));
|
||||
session.setTransactionIsolation(Session::TRANSACTION_READ_COMMITTED);
|
||||
|
||||
TestCommitTransactor ct;
|
||||
Transaction t1(session, ct);
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (1 == count);
|
||||
|
||||
session << "DELETE FROM Person", now;
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (0 == count);
|
||||
|
||||
try
|
||||
{
|
||||
TestRollbackTransactor rt;
|
||||
Transaction t(session, rt);
|
||||
fail ("must fail");
|
||||
} catch (Poco::Exception&) { }
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (0 == count);
|
||||
|
||||
try
|
||||
{
|
||||
TestRollbackTransactor rt;
|
||||
Transaction t(session);
|
||||
t.transact(rt);
|
||||
fail ("must fail");
|
||||
} catch (Poco::Exception&) { }
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (0 == count);
|
||||
|
||||
try
|
||||
{
|
||||
TestRollbackTransactor rt;
|
||||
Transaction t(session, false);
|
||||
t.transact(rt);
|
||||
fail ("must fail");
|
||||
} catch (Poco::Exception&) { }
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (0 == count);
|
||||
|
||||
try
|
||||
{
|
||||
TestRollbackTransactor rt;
|
||||
Transaction t(session, true);
|
||||
t.transact(rt);
|
||||
fail ("must fail");
|
||||
} catch (Poco::Exception&) { }
|
||||
|
||||
session << "SELECT count(*) FROM Person", into(count), now;
|
||||
assert (0 == count);
|
||||
|
||||
session.close();
|
||||
assert (!session.isConnected());
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::setUp()
|
||||
{
|
||||
}
|
||||
@@ -2872,6 +3304,11 @@ CppUnit::Test* SQLiteTest::suite()
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testSystemTable);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testThreadModes);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testUpdateCallback);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testCommitCallback);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testRollbackCallback);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testSessionTransaction);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testTransaction);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testTransactor);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@@ -40,6 +40,14 @@
|
||||
#include "CppUnit/TestCase.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
class Session;
|
||||
|
||||
} }
|
||||
|
||||
|
||||
class SQLiteTest: public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
@@ -137,15 +145,25 @@ public:
|
||||
void testThreadModes();
|
||||
|
||||
void testUpdateCallback();
|
||||
void testCommitCallback();
|
||||
void testRollbackCallback();
|
||||
|
||||
void testSessionTransaction();
|
||||
void testTransaction();
|
||||
void testTransactor();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
static void sqliteUpdateCallbackFn(void*, int, const char*, const char*, Poco::Int64);
|
||||
static int sqliteCommitCallbackFn(void*);
|
||||
static void sqliteRollbackCallbackFn(void*);
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti);
|
||||
|
||||
static int _insertCounter;
|
||||
static int _updateCounter;
|
||||
static int _deleteCounter;
|
||||
|
@@ -81,14 +81,14 @@ public:
|
||||
Poco::UInt32 getTransactionIsolation();
|
||||
bool hasTransactionIsolation(Poco::UInt32);
|
||||
bool isTransactionIsolation(Poco::UInt32);
|
||||
const std::string& connectorName();
|
||||
const std::string& connectorName() const;
|
||||
void setFeature(const std::string& name, bool state);
|
||||
bool getFeature(const std::string& name);
|
||||
void setProperty(const std::string& name, const Poco::Any& value);
|
||||
Poco::Any getProperty(const std::string& name);
|
||||
|
||||
protected:
|
||||
SessionImpl* access();
|
||||
SessionImpl* access() const;
|
||||
/// Updates the last access timestamp,
|
||||
/// verifies validity of the session
|
||||
/// and returns the session if it is valid.
|
||||
@@ -96,18 +96,18 @@ protected:
|
||||
/// Throws an SessionUnavailableException if the
|
||||
/// session is no longer valid.
|
||||
|
||||
SessionImpl* impl();
|
||||
SessionImpl* impl() const;
|
||||
/// Returns a pointer to the SessionImpl.
|
||||
|
||||
private:
|
||||
Poco::AutoPtr<PooledSessionHolder> _pHolder;
|
||||
mutable Poco::AutoPtr<PooledSessionHolder> _pHolder;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline SessionImpl* PooledSessionImpl::impl()
|
||||
inline SessionImpl* PooledSessionImpl::impl() const
|
||||
{
|
||||
return _pHolder->session();
|
||||
}
|
||||
|
@@ -274,10 +274,10 @@ public:
|
||||
/// Returns true iff the transaction isolation level corresponds
|
||||
/// to the supplied bitmask.
|
||||
|
||||
std::string connector();
|
||||
std::string connector() const;
|
||||
/// Returns the connector name for this session.
|
||||
|
||||
std::string uri();
|
||||
std::string uri() const;
|
||||
/// Returns the URI for this session.
|
||||
|
||||
static std::string uri(const std::string& connector,
|
||||
@@ -443,7 +443,7 @@ inline bool Session::isTransactionIsolation(Poco::UInt32 ti)
|
||||
}
|
||||
|
||||
|
||||
inline std::string Session::connector()
|
||||
inline std::string Session::connector() const
|
||||
{
|
||||
return _pImpl->connectorName();
|
||||
}
|
||||
@@ -456,7 +456,7 @@ inline std::string Session::uri(const std::string& connector,
|
||||
}
|
||||
|
||||
|
||||
inline std::string Session::uri()
|
||||
inline std::string Session::uri() const
|
||||
{
|
||||
return _pImpl->uri();
|
||||
}
|
||||
|
@@ -139,16 +139,16 @@ public:
|
||||
/// Returns true iff the transaction isolation level corresponds
|
||||
/// to the supplied bitmask.
|
||||
|
||||
virtual const std::string& connectorName() = 0;
|
||||
virtual const std::string& connectorName() const = 0;
|
||||
/// Returns the name of the connector.
|
||||
|
||||
const std::string& connectionString();
|
||||
const std::string& connectionString() const;
|
||||
/// Returns the connection string.
|
||||
|
||||
static std::string uri(const std::string& connector, const std::string& connectionString);
|
||||
/// Returns formatted URI.
|
||||
|
||||
std::string uri();
|
||||
std::string uri() const;
|
||||
/// Returns the URI for this session.
|
||||
|
||||
virtual void setFeature(const std::string& name, bool state) = 0;
|
||||
@@ -206,7 +206,7 @@ private:
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline const std::string& SessionImpl::connectionString()
|
||||
inline const std::string& SessionImpl::connectionString() const
|
||||
{
|
||||
return _connectionString;
|
||||
}
|
||||
@@ -231,7 +231,7 @@ inline std::string SessionImpl::uri(const std::string& connector,
|
||||
}
|
||||
|
||||
|
||||
inline std::string SessionImpl::uri()
|
||||
inline std::string SessionImpl::uri() const
|
||||
{
|
||||
return uri(connectorName(), connectionString());
|
||||
}
|
||||
|
@@ -163,7 +163,7 @@ void PooledSessionImpl::close()
|
||||
}
|
||||
|
||||
|
||||
const std::string& PooledSessionImpl::connectorName()
|
||||
const std::string& PooledSessionImpl::connectorName() const
|
||||
{
|
||||
return access()->connectorName();
|
||||
}
|
||||
@@ -193,7 +193,7 @@ Poco::Any PooledSessionImpl::getProperty(const std::string& name)
|
||||
}
|
||||
|
||||
|
||||
SessionImpl* PooledSessionImpl::access()
|
||||
SessionImpl* PooledSessionImpl::access() const
|
||||
{
|
||||
if (_pHolder)
|
||||
{
|
||||
|
@@ -476,7 +476,8 @@ void StatementImpl::formatSQL(std::vector<Any>& arguments)
|
||||
{
|
||||
std::string sql;
|
||||
Poco::format(sql, _ostr.str(), arguments);
|
||||
_ostr.str(""); _ostr << sql;
|
||||
_ostr.str("");
|
||||
_ostr << sql;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -145,7 +145,7 @@ bool SessionImpl::isTransactionIsolation(Poco::UInt32)
|
||||
}
|
||||
|
||||
|
||||
const std::string& SessionImpl::connectorName()
|
||||
const std::string& SessionImpl::connectorName() const
|
||||
{
|
||||
return Connector::KEY;
|
||||
}
|
||||
|
@@ -105,7 +105,7 @@ public:
|
||||
/// Returns true iff the transaction isolation level corresponds
|
||||
/// to the supplied bitmask.
|
||||
|
||||
const std::string& connectorName();
|
||||
const std::string& connectorName() const;
|
||||
/// Returns the name of the connector.
|
||||
|
||||
void setConnected(const std::string& name, bool value);
|
||||
|
Reference in New Issue
Block a user