fix(Data::Session): Set autoCommit to false in Session #4167 #4143

This commit is contained in:
Alex Fabijanic
2023-10-25 22:40:41 +02:00
parent e47b92d641
commit bd06526ee0
11 changed files with 126 additions and 120 deletions

View File

@@ -1275,14 +1275,10 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
{ {
SessionPool pool("ODBC", connectString, 1, 4, 2, 10); SessionPool pool("ODBC", connectString, 1, 4, 2, 10);
pool.setFeature("f1", true); try { pool.getFeature("g1"); fail ("getting an unsuported feature must fail"); }
assertTrue (pool.getFeature("f1"));
try { pool.getFeature("g1"); fail ("must fail"); }
catch ( Poco::NotFoundException& ) { } catch ( Poco::NotFoundException& ) { }
pool.setProperty("p1", 1); try { pool.getProperty("r1"); fail ("getting an unsuported property must fail"); }
assertTrue (1 == Poco::AnyCast<int>(pool.getProperty("p1")));
try { pool.getProperty("r1"); fail ("must fail"); }
catch ( Poco::NotFoundException& ) { } catch ( Poco::NotFoundException& ) { }
assertTrue (pool.capacity() == 4); assertTrue (pool.capacity() == 4);
@@ -1294,14 +1290,15 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.allocated() == pool.used() + pool.idle()); assertTrue (pool.allocated() == pool.used() + pool.idle());
Session s1(pool.get()); Session s1(pool.get());
assertTrue (s1.getFeature("f1")); try { pool.setFeature("f1", true); fail ("setting an unsuported feature must fail"); }
assertTrue (1 == Poco::AnyCast<int>(s1.getProperty("p1"))); catch (Poco::InvalidAccessException&) { }
catch (Poco::NotImplementedException&) { }
catch (Poco::Data::NotSupportedException&) { }
try { pool.setFeature("f1", true); fail ("must fail"); } try { pool.setProperty("p1", 1); fail ("setting an unsuported property must fail"); }
catch ( Poco::InvalidAccessException& ) { } catch (Poco::InvalidAccessException&) { }
catch (Poco::NotImplementedException&) { }
try { pool.setProperty("p1", 1); fail ("must fail"); } catch (Poco::Data::NotSupportedException&) { }
catch ( Poco::InvalidAccessException& ) { }
assertTrue (pool.capacity() == 4); assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 1); assertTrue (pool.allocated() == 1);
@@ -1311,10 +1308,7 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.dead() == 0); assertTrue (pool.dead() == 0);
assertTrue (pool.allocated() == pool.used() + pool.idle()); assertTrue (pool.allocated() == pool.used() + pool.idle());
Session s2(pool.get("f1", false)); Session s2(pool.get());
assertTrue (!s2.getFeature("f1"));
assertTrue (1 == Poco::AnyCast<int>(s2.getProperty("p1")));
assertTrue (pool.capacity() == 4); assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 2); assertTrue (pool.allocated() == 2);
assertTrue (pool.idle() == 0); assertTrue (pool.idle() == 0);
@@ -1323,32 +1317,7 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.dead() == 0); assertTrue (pool.dead() == 0);
assertTrue (pool.allocated() == pool.used() + pool.idle()); assertTrue (pool.allocated() == pool.used() + pool.idle());
{
Session s3(pool.get("p1", 2));
assertTrue (s3.getFeature("f1"));
assertTrue (2 == Poco::AnyCast<int>(s3.getProperty("p1")));
assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 3);
assertTrue (pool.idle() == 0);
assertTrue (pool.connTimeout() == 10);
assertTrue (pool.available() == 1);
assertTrue (pool.dead() == 0);
assertTrue (pool.allocated() == pool.used() + pool.idle());
}
assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 3);
assertTrue (pool.idle() == 1);
assertTrue (pool.connTimeout() == 10);
assertTrue (pool.available() == 2);
assertTrue (pool.dead() == 0);
assertTrue (pool.allocated() == pool.used() + pool.idle());
Session s4(pool.get()); Session s4(pool.get());
assertTrue (s4.getFeature("f1"));
assertTrue (1 == Poco::AnyCast<int>(s4.getProperty("p1")));
assertTrue (pool.capacity() == 4); assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 3); assertTrue (pool.allocated() == 3);
assertTrue (pool.idle() == 0); assertTrue (pool.idle() == 0);
@@ -1358,7 +1327,6 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.allocated() == pool.used() + pool.idle()); assertTrue (pool.allocated() == pool.used() + pool.idle());
Session s5(pool.get()); Session s5(pool.get());
assertTrue (pool.capacity() == 4); assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 4); assertTrue (pool.allocated() == 4);
assertTrue (pool.idle() == 0); assertTrue (pool.idle() == 0);
@@ -1419,13 +1387,10 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.dead() == 0); assertTrue (pool.dead() == 0);
assertTrue (pool.allocated() == pool.used() + pool.idle()); assertTrue (pool.allocated() == pool.used() + pool.idle());
s6.setFeature("connected", false);
assertTrue (pool.dead() == 1);
s6.close(); s6.close();
assertTrue (pool.capacity() == 4); assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 2); assertTrue (pool.allocated() == 3);
assertTrue (pool.idle() == 0); assertTrue (pool.idle() == 1);
assertTrue (pool.connTimeout() == 10); assertTrue (pool.connTimeout() == 10);
assertTrue (pool.available() == 2); assertTrue (pool.available() == 2);
assertTrue (pool.dead() == 0); assertTrue (pool.dead() == 0);
@@ -1447,7 +1412,9 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.connTimeout() == 10); assertTrue (pool.connTimeout() == 10);
assertTrue (pool.available() == 0); assertTrue (pool.available() == 0);
assertTrue (pool.dead() == 0); assertTrue (pool.dead() == 0);
assertTrue (pool.allocated() == pool.used() + pool.idle()); assertTrue (pool.allocated() == 0);
assertTrue (pool.used() == 0);
assertTrue (pool.idle() == 0);
} }
} }
@@ -4214,9 +4181,8 @@ void SQLExecutor::sessionTransaction(const std::string& connect)
} }
Session local("odbc", connect); Session local("odbc", connect);
local.setFeature("autoCommit", true);
std::string funct = "transaction()"; std::string funct = "sessionTransaction()";
std::vector<std::string> lastNames; std::vector<std::string> lastNames;
std::vector<std::string> firstNames; std::vector<std::string> firstNames;
std::vector<std::string> addresses; std::vector<std::string> addresses;
@@ -4240,10 +4206,13 @@ void SQLExecutor::sessionTransaction(const std::string& connect)
session().setFeature("autoCommit", false); session().setFeature("autoCommit", false);
assertTrue (!session().isTransaction()); assertTrue (!session().isTransaction());
auto ti = session().getTransactionIsolation();
// these are just calls to check the transactional capabilities of the session
// they will print diagnostics to stderr if a transaction isolation level is not supported
setTransactionIsolation(session(), Session::TRANSACTION_READ_UNCOMMITTED); setTransactionIsolation(session(), Session::TRANSACTION_READ_UNCOMMITTED);
setTransactionIsolation(session(), Session::TRANSACTION_REPEATABLE_READ); setTransactionIsolation(session(), Session::TRANSACTION_REPEATABLE_READ);
setTransactionIsolation(session(), Session::TRANSACTION_SERIALIZABLE); setTransactionIsolation(session(), Session::TRANSACTION_SERIALIZABLE);
setTransactionIsolation(session(), Session::TRANSACTION_READ_COMMITTED); setTransactionIsolation(session(), Session::TRANSACTION_READ_COMMITTED);
session().begin(); session().begin();
@@ -4291,7 +4260,9 @@ void SQLExecutor::sessionTransaction(const std::string& connect)
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assertTrue (2 == count); assertTrue (2 == count);
// restore the original transaction state
session().setFeature("autoCommit", autoCommit); session().setFeature("autoCommit", autoCommit);
setTransactionIsolation(session(), ti);
} }
@@ -4306,6 +4277,9 @@ void SQLExecutor::transaction(const std::string& connect)
Session local("odbc", connect); Session local("odbc", connect);
local.setFeature("autoCommit", true); local.setFeature("autoCommit", true);
bool autoCommit = session().getFeature("autoCommit");
auto ti = session().getTransactionIsolation();
setTransactionIsolation(session(), Session::TRANSACTION_READ_COMMITTED); setTransactionIsolation(session(), Session::TRANSACTION_READ_COMMITTED);
if (local.hasTransactionIsolation(Session::TRANSACTION_READ_UNCOMMITTED)) if (local.hasTransactionIsolation(Session::TRANSACTION_READ_UNCOMMITTED))
setTransactionIsolation(local, Session::TRANSACTION_READ_UNCOMMITTED); setTransactionIsolation(local, Session::TRANSACTION_READ_UNCOMMITTED);
@@ -4329,8 +4303,6 @@ void SQLExecutor::transaction(const std::string& connect)
int count = 0, locCount = 0; int count = 0, locCount = 0;
std::string result; std::string result;
bool autoCommit = session().getFeature("autoCommit");
session().setFeature("autoCommit", true); session().setFeature("autoCommit", true);
assertTrue (!session().isTransaction()); assertTrue (!session().isTransaction());
session().setFeature("autoCommit", false); session().setFeature("autoCommit", false);
@@ -4454,7 +4426,9 @@ void SQLExecutor::transaction(const std::string& connect)
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assertTrue (2 == count); assertTrue (2 == count);
// restore the original transaction state
session().setFeature("autoCommit", autoCommit); session().setFeature("autoCommit", autoCommit);
setTransactionIsolation(session(), ti);
} }

View File

@@ -115,7 +115,7 @@ public:
{ {
} }
bool hasFeature(const std::string& name) bool hasFeature(const std::string& name) const
/// Looks a feature up in the features map /// Looks a feature up in the features map
/// and returns true if there is one. /// and returns true if there is one.
{ {
@@ -140,7 +140,7 @@ public:
else throw NotSupportedException(name); else throw NotSupportedException(name);
} }
bool getFeature(const std::string& name) bool getFeature(const std::string& name) const
/// Looks a feature up in the features map /// Looks a feature up in the features map
/// and calls the feature's getter, if there is one. /// and calls the feature's getter, if there is one.
{ {
@@ -148,14 +148,14 @@ public:
if (it != _features.end()) if (it != _features.end())
{ {
if (it->second.getter) if (it->second.getter)
return (static_cast<C*>(this)->*it->second.getter)(name); return (static_cast<const C*>(this)->*it->second.getter)(name);
else else
throw NotImplementedException("get", name); throw NotImplementedException("get", name);
} }
else throw NotSupportedException(name); else throw NotSupportedException(name);
} }
bool hasProperty(const std::string& name) bool hasProperty(const std::string& name) const
/// Looks a property up in the properties map /// Looks a property up in the properties map
/// and returns true if there is one. /// and returns true if there is one.
{ {
@@ -180,7 +180,7 @@ public:
else throw NotSupportedException(name); else throw NotSupportedException(name);
} }
Poco::Any getProperty(const std::string& name) Poco::Any getProperty(const std::string& name) const
/// Looks a property up in the properties map /// Looks a property up in the properties map
/// and calls the property's getter, if there is one. /// and calls the property's getter, if there is one.
{ {
@@ -188,7 +188,7 @@ public:
if (it != _properties.end()) if (it != _properties.end())
{ {
if (it->second.getter) if (it->second.getter)
return (static_cast<C*>(this)->*it->second.getter)(name); return (static_cast<const C*>(this)->*it->second.getter)(name);
else else
throw NotImplementedException("set", name); throw NotImplementedException("set", name);
} }

View File

@@ -62,12 +62,12 @@ public:
bool hasTransactionIsolation(Poco::UInt32) const; bool hasTransactionIsolation(Poco::UInt32) const;
bool isTransactionIsolation(Poco::UInt32) const; bool isTransactionIsolation(Poco::UInt32) const;
const std::string& connectorName() const; const std::string& connectorName() const;
bool hasFeature(const std::string& name); bool hasFeature(const std::string& name) const;
void setFeature(const std::string& name, bool state); void setFeature(const std::string& name, bool state);
bool getFeature(const std::string& name); bool getFeature(const std::string& name) const;
bool hasProperty(const std::string& name); bool hasProperty(const std::string& name) const;
void setProperty(const std::string& name, const Poco::Any& value); void setProperty(const std::string& name, const Poco::Any& value);
Poco::Any getProperty(const std::string& name); Poco::Any getProperty(const std::string& name) const;
protected: protected:
SessionImpl* access() const; SessionImpl* access() const;

View File

@@ -151,6 +151,12 @@ class Data_API Session
/// If the formatting will occur and the percent sign is part of the query itself, it can be passed to the query by entering it twice (%%). /// If the formatting will occur and the percent sign is part of the query itself, it can be passed to the query by entering it twice (%%).
/// However, if no formatting is used, one percent sign is sufficient as the string will be passed unaltered. /// However, if no formatting is used, one percent sign is sufficient as the string will be passed unaltered.
/// For complete list of supported data types with their respective specifications, see the documentation for format in Foundation. /// For complete list of supported data types with their respective specifications, see the documentation for format in Foundation.
///
/// Transactions are supported via the begin(), commit() and rollback() methods.
/// If the session is in autocommit mode, begin() will temporarily disable autocommit mode for the duration of the transaction.
/// Calls to either commit() or rollback() will re-enable it.
/// Poco::Data::Transaction, a convenient session wrapper class, automates this process and provides RAII-based transactional behavior.
/// For more information, see Transation class documentation.
{ {
public: public:
static const std::size_t LOGIN_TIMEOUT_DEFAULT = SessionImpl::LOGIN_TIMEOUT_DEFAULT; static const std::size_t LOGIN_TIMEOUT_DEFAULT = SessionImpl::LOGIN_TIMEOUT_DEFAULT;
@@ -160,7 +166,7 @@ public:
static const Poco::UInt32 TRANSACTION_SERIALIZABLE = 0x00000008L; static const Poco::UInt32 TRANSACTION_SERIALIZABLE = 0x00000008L;
Session(Poco::AutoPtr<SessionImpl> ptrImpl); Session(Poco::AutoPtr<SessionImpl> ptrImpl);
/// Creates the Session. /// Creates the Session from SessionImpl.
Session(const std::string& connector, Session(const std::string& connector,
const std::string& connectionString, const std::string& connectionString,
@@ -221,6 +227,13 @@ public:
bool isGood(); bool isGood();
/// Returns true iff the session is good and can be used, false otherwise. /// Returns true iff the session is good and can be used, false otherwise.
bool isAutocommit() const;
/// Returns true iff the session is in autocommit mode, false otherwise.
/// If the session does not support autocommit, it is assumed not to
/// be in auto commit mode.
/// This function looks for the "autoCommit" feature and returns its value.
/// It is recommended for all back-end implementations to support this feature.
void setLoginTimeout(std::size_t timeout); void setLoginTimeout(std::size_t timeout);
/// Sets the session login timeout value. /// Sets the session login timeout value.
@@ -235,12 +248,19 @@ public:
void begin(); void begin();
/// Starts a transaction. /// Starts a transaction.
/// If `session` is in autocommit mode, it is switched to manual commit mode
/// for the duration of the transaction and reverted back to the original mode
/// after transaction completes (on rollback or commit() call).
void commit(); void commit();
/// Commits and ends a transaction. /// Commits and ends a transaction.
/// If `session` was in autocommit mode when the transaction started (begin() call),
/// it is switched back to autocommit mode.
void rollback(); void rollback();
/// Rolls back and ends a transaction. /// Rolls back and ends a transaction.
/// If `session` was in autocommit mode when the transaction started (begin() call),
/// it is switched back to autocommit mode.
bool canTransact(); bool canTransact();
/// Returns true if session has transaction capabilities. /// Returns true if session has transaction capabilities.
@@ -273,7 +293,7 @@ public:
/// Utility function that teturns the URI formatted from supplied /// Utility function that teturns the URI formatted from supplied
/// arguments as "connector:///connectionString". /// arguments as "connector:///connectionString".
bool hasFeature(const std::string& name); bool hasFeature(const std::string& name) const;
/// Returns true if session has the named feature. /// Returns true if session has the named feature.
void setFeature(const std::string& name, bool state); void setFeature(const std::string& name, bool state);
@@ -294,7 +314,7 @@ public:
/// Throws a NotSupportedException if the requested feature is /// Throws a NotSupportedException if the requested feature is
/// not supported by the underlying implementation. /// not supported by the underlying implementation.
bool hasProperty(const std::string& name); bool hasProperty(const std::string& name) const;
/// Returns true if session has the named property. /// Returns true if session has the named property.
void setProperty(const std::string& name, const Poco::Any& value); void setProperty(const std::string& name, const Poco::Any& value);
@@ -322,13 +342,21 @@ private:
Session(); Session();
Poco::AutoPtr<SessionImpl> _pImpl; Poco::AutoPtr<SessionImpl> _pImpl;
StatementCreator _statementCreator; StatementCreator _statementCreator;
bool _wasAutoCommit = false;
}; };
// //
// inlines // inlines
// //
inline bool Session::isAutocommit() const
{
return hasFeature("autoCommit") && getFeature("autoCommit");
}
inline SharedPtr<StatementImpl> Session::createStatementImpl() inline SharedPtr<StatementImpl> Session::createStatementImpl()
{ {
return _pImpl->createStatementImpl(); return _pImpl->createStatementImpl();
@@ -389,24 +417,6 @@ inline std::size_t Session::getConnectionTimeout()
} }
inline void Session::begin()
{
return _pImpl->begin();
}
inline void Session::commit()
{
return _pImpl->commit();
}
inline void Session::rollback()
{
return _pImpl->rollback();
}
inline bool Session::canTransact() inline bool Session::canTransact()
{ {
return _pImpl->canTransact(); return _pImpl->canTransact();
@@ -462,7 +472,7 @@ inline std::string Session::uri() const
} }
inline bool Session::hasFeature(const std::string& name) inline bool Session::hasFeature(const std::string& name) const
{ {
return _pImpl->hasFeature(name); return _pImpl->hasFeature(name);
} }
@@ -480,7 +490,7 @@ inline bool Session::getFeature(const std::string& name) const
} }
inline bool Session::hasProperty(const std::string& name) inline bool Session::hasProperty(const std::string& name) const
{ {
return _pImpl->hasProperty(name); return _pImpl->hasProperty(name);
} }

View File

@@ -146,7 +146,7 @@ public:
std::string uri() const; std::string uri() const;
/// Returns the URI for this session. /// Returns the URI for this session.
virtual bool hasFeature(const std::string& name) = 0; virtual bool hasFeature(const std::string& name) const = 0;
/// Returns true if session has the named feature. /// Returns true if session has the named feature.
virtual void setFeature(const std::string& name, bool state) = 0; virtual void setFeature(const std::string& name, bool state) = 0;
@@ -158,7 +158,7 @@ public:
/// Throws a NotSupportedException if the requested feature is /// Throws a NotSupportedException if the requested feature is
/// not supported by the underlying implementation. /// not supported by the underlying implementation.
virtual bool getFeature(const std::string& name) = 0; virtual bool getFeature(const std::string& name) const = 0;
/// Look up the state of a feature. /// Look up the state of a feature.
/// ///
/// Features are a generic extension mechanism for session implementations. /// Features are a generic extension mechanism for session implementations.
@@ -167,7 +167,7 @@ public:
/// Throws a NotSupportedException if the requested feature is /// Throws a NotSupportedException if the requested feature is
/// not supported by the underlying implementation. /// not supported by the underlying implementation.
virtual bool hasProperty(const std::string& name) = 0; virtual bool hasProperty(const std::string& name) const = 0;
/// Returns true if session has the named feature. /// Returns true if session has the named feature.
virtual void setProperty(const std::string& name, const Poco::Any& value) = 0; virtual void setProperty(const std::string& name, const Poco::Any& value) = 0;
@@ -179,7 +179,7 @@ public:
/// Throws a NotSupportedException if the requested property is /// Throws a NotSupportedException if the requested property is
/// not supported by the underlying implementation. /// not supported by the underlying implementation.
virtual Poco::Any getProperty(const std::string& name) = 0; virtual Poco::Any getProperty(const std::string& name) const = 0;
/// Look up the value of a property. /// Look up the value of a property.
/// ///
/// Properties are a generic extension mechanism for session implementations. /// Properties are a generic extension mechanism for session implementations.

View File

@@ -146,13 +146,13 @@ public:
void setFeature(const std::string& name, bool state); void setFeature(const std::string& name, bool state);
/// Sets feature for all the sessions. /// Sets feature for all the sessions.
bool getFeature(const std::string& name); bool getFeature(const std::string& name) const;
/// Returns the requested feature. /// Returns the requested feature.
void setProperty(const std::string& name, const Poco::Any& value); void setProperty(const std::string& name, const Poco::Any& value);
/// Sets property for all sessions. /// Sets property for all sessions.
Poco::Any getProperty(const std::string& name); Poco::Any getProperty(const std::string& name) const;
/// Returns the requested property. /// Returns the requested property.
void shutdown(); void shutdown();

View File

@@ -39,9 +39,6 @@ class Data_API Transaction
public: public:
Transaction(Poco::Data::Session& session, Poco::Logger* pLogger = 0); Transaction(Poco::Data::Session& session, Poco::Logger* pLogger = 0);
/// Creates the Transaction and starts it, using the given database session and logger. /// Creates the Transaction and starts it, using the given database session and logger.
/// If `session` is in autocommit mode, it is switched to manual commit mode
/// for the duration of the transaction and reverted back to the original mode
/// after transaction completes.
Transaction(Poco::Data::Session& session, bool start); Transaction(Poco::Data::Session& session, bool start);
/// Creates the Transaction, using the given database session. /// Creates the Transaction, using the given database session.
@@ -159,7 +156,6 @@ private:
/// Otherwise does nothing. /// Otherwise does nothing.
Session _rSession; Session _rSession;
bool _autoCommit = false;
Logger* _pLogger = nullptr; Logger* _pLogger = nullptr;
}; };

View File

@@ -166,7 +166,7 @@ const std::string& PooledSessionImpl::connectorName() const
} }
bool PooledSessionImpl::hasFeature(const std::string& name) bool PooledSessionImpl::hasFeature(const std::string& name) const
{ {
return access()->hasFeature(name); return access()->hasFeature(name);
} }
@@ -178,13 +178,13 @@ void PooledSessionImpl::setFeature(const std::string& name, bool state)
} }
bool PooledSessionImpl::getFeature(const std::string& name) bool PooledSessionImpl::getFeature(const std::string& name) const
{ {
return access()->getFeature(name); return access()->getFeature(name);
} }
bool PooledSessionImpl::hasProperty(const std::string& name) bool PooledSessionImpl::hasProperty(const std::string& name) const
{ {
return access()->hasProperty(name); return access()->hasProperty(name);
} }
@@ -196,7 +196,7 @@ void PooledSessionImpl::setProperty(const std::string& name, const Poco::Any& va
} }
Poco::Any PooledSessionImpl::getProperty(const std::string& name) Poco::Any PooledSessionImpl::getProperty(const std::string& name) const
{ {
return access()->getProperty(name); return access()->getProperty(name);
} }

View File

@@ -25,9 +25,9 @@ namespace Data {
Session::Session(Poco::AutoPtr<SessionImpl> pImpl): Session::Session(Poco::AutoPtr<SessionImpl> pImpl):
_pImpl(pImpl), _pImpl(pImpl),
_statementCreator(pImpl) _statementCreator(pImpl),
_wasAutoCommit(false)
{ {
poco_check_ptr (pImpl.get());
} }
@@ -40,8 +40,7 @@ Session::Session(const std::string& connector,
} }
Session::Session(const std::string& connection, Session::Session(const std::string& connection, std::size_t timeout)
std::size_t timeout)
{ {
Session newSession(SessionFactory::instance().create(connection, timeout)); Session newSession(SessionFactory::instance().create(connection, timeout));
swap(newSession); swap(newSession);
@@ -50,14 +49,16 @@ Session::Session(const std::string& connection,
Session::Session(const Session& other): Session::Session(const Session& other):
_pImpl(other._pImpl), _pImpl(other._pImpl),
_statementCreator(other._statementCreator) _statementCreator(other._statementCreator),
_wasAutoCommit(other._wasAutoCommit)
{ {
} }
Session::Session(Session&& other) noexcept: Session::Session(Session&& other) noexcept:
_pImpl(std::move(other._pImpl)), _pImpl(std::move(other._pImpl)),
_statementCreator(std::move(other._statementCreator)) _statementCreator(std::move(other._statementCreator)),
_wasAutoCommit(other._wasAutoCommit)
{ {
} }
@@ -78,6 +79,7 @@ Session& Session::operator = (Session&& other) noexcept
{ {
_pImpl = std::move(other._pImpl); _pImpl = std::move(other._pImpl);
_statementCreator = std::move(other._statementCreator); _statementCreator = std::move(other._statementCreator);
_wasAutoCommit = other._wasAutoCommit;
return *this; return *this;
} }
@@ -87,6 +89,40 @@ void Session::swap(Session& other)
using std::swap; using std::swap;
swap(_statementCreator, other._statementCreator); swap(_statementCreator, other._statementCreator);
swap(_pImpl, other._pImpl); swap(_pImpl, other._pImpl);
swap(_wasAutoCommit, other._wasAutoCommit);
}
void Session::begin()
{
if (isAutocommit())
{
setFeature("autoCommit", false);
_wasAutoCommit = true;
}
return _pImpl->begin();
}
void Session::commit()
{
_pImpl->commit();
if (_wasAutoCommit)
{
setFeature("autoCommit", true);
_wasAutoCommit = false;
}
}
void Session::rollback()
{
_pImpl->rollback();
if (_wasAutoCommit)
{
setFeature("autoCommit", true);
_wasAutoCommit = false;
}
} }

View File

@@ -178,7 +178,7 @@ void SessionPool::setFeature(const std::string& name, bool state)
} }
bool SessionPool::getFeature(const std::string& name) bool SessionPool::getFeature(const std::string& name) const
{ {
if (_shutdown) throw InvalidAccessException("Session pool has been shut down."); if (_shutdown) throw InvalidAccessException("Session pool has been shut down.");
@@ -205,7 +205,7 @@ void SessionPool::setProperty(const std::string& name, const Poco::Any& value)
} }
Poco::Any SessionPool::getProperty(const std::string& name) Poco::Any SessionPool::getProperty(const std::string& name) const
{ {
Poco::Mutex::ScopedLock lock(_mutex); Poco::Mutex::ScopedLock lock(_mutex);
PropertyMap::ConstIterator it = _propertyMap.find(name); PropertyMap::ConstIterator it = _propertyMap.find(name);

View File

@@ -22,7 +22,6 @@ namespace Data {
Transaction::Transaction(Poco::Data::Session& rSession, Poco::Logger* pLogger): Transaction::Transaction(Poco::Data::Session& rSession, Poco::Logger* pLogger):
_rSession(rSession), _rSession(rSession),
_autoCommit(_rSession.hasFeature("autoCommit") ? _rSession.getFeature("autoCommit") : false),
_pLogger(pLogger) _pLogger(pLogger)
{ {
begin(); begin();
@@ -31,7 +30,6 @@ Transaction::Transaction(Poco::Data::Session& rSession, Poco::Logger* pLogger):
Transaction::Transaction(Poco::Data::Session& rSession, bool start): Transaction::Transaction(Poco::Data::Session& rSession, bool start):
_rSession(rSession), _rSession(rSession),
_autoCommit(_rSession.hasFeature("autoCommit") ? _rSession.getFeature("autoCommit") : false),
_pLogger(0) _pLogger(0)
{ {
if (start) begin(); if (start) begin();
@@ -73,11 +71,7 @@ Transaction::~Transaction()
void Transaction::begin() void Transaction::begin()
{ {
if (!_rSession.isTransaction()) if (!_rSession.isTransaction())
{
if (_autoCommit)
_rSession.setFeature("autoCommit", false);
_rSession.begin(); _rSession.begin();
}
else else
throw InvalidAccessException("Transaction in progress."); throw InvalidAccessException("Transaction in progress.");
} }
@@ -122,8 +116,6 @@ void Transaction::commit()
_pLogger->debug("Committing transaction."); _pLogger->debug("Committing transaction.");
_rSession.commit(); _rSession.commit();
if (_autoCommit)
_rSession.setFeature("autoCommit", true);
} }
@@ -133,8 +125,6 @@ void Transaction::rollback()
_pLogger->debug("Rolling back transaction."); _pLogger->debug("Rolling back transaction.");
_rSession.rollback(); _rSession.rollback();
if (_autoCommit)
_rSession.setFeature("autoCommit", true);
} }