Skip to content

Commit

Permalink
fix(Data::Session): Set autoCommit to false in Session #4167 #4143
Browse files Browse the repository at this point in the history
  • Loading branch information
aleks-f committed Oct 25, 2023
1 parent e47b92d commit bd06526
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 120 deletions.
82 changes: 28 additions & 54 deletions Data/ODBC/testsuite/src/SQLExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1275,14 +1275,10 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
{
SessionPool pool("ODBC", connectString, 1, 4, 2, 10);

pool.setFeature("f1", true);
assertTrue (pool.getFeature("f1"));
try { pool.getFeature("g1"); fail ("must fail"); }
try { pool.getFeature("g1"); fail ("getting an unsuported feature must fail"); }
catch ( Poco::NotFoundException& ) { }

pool.setProperty("p1", 1);
assertTrue (1 == Poco::AnyCast<int>(pool.getProperty("p1")));
try { pool.getProperty("r1"); fail ("must fail"); }
try { pool.getProperty("r1"); fail ("getting an unsuported property must fail"); }
catch ( Poco::NotFoundException& ) { }

assertTrue (pool.capacity() == 4);
Expand All @@ -1294,14 +1290,15 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.allocated() == pool.used() + pool.idle());
Session s1(pool.get());

assertTrue (s1.getFeature("f1"));
assertTrue (1 == Poco::AnyCast<int>(s1.getProperty("p1")));
try { pool.setFeature("f1", true); fail ("setting an unsuported feature must fail"); }
catch (Poco::InvalidAccessException&) { }
catch (Poco::NotImplementedException&) { }
catch (Poco::Data::NotSupportedException&) { }

try { pool.setFeature("f1", true); fail ("must fail"); }
catch ( Poco::InvalidAccessException& ) { }

try { pool.setProperty("p1", 1); fail ("must fail"); }
catch ( Poco::InvalidAccessException& ) { }
try { pool.setProperty("p1", 1); fail ("setting an unsuported property must fail"); }
catch (Poco::InvalidAccessException&) { }
catch (Poco::NotImplementedException&) { }
catch (Poco::Data::NotSupportedException&) { }

assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 1);
Expand All @@ -1311,10 +1308,7 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.dead() == 0);
assertTrue (pool.allocated() == pool.used() + pool.idle());

Session s2(pool.get("f1", false));
assertTrue (!s2.getFeature("f1"));
assertTrue (1 == Poco::AnyCast<int>(s2.getProperty("p1")));

Session s2(pool.get());
assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 2);
assertTrue (pool.idle() == 0);
Expand All @@ -1323,32 +1317,7 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.dead() == 0);
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());
assertTrue (s4.getFeature("f1"));
assertTrue (1 == Poco::AnyCast<int>(s4.getProperty("p1")));

assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 3);
assertTrue (pool.idle() == 0);
Expand All @@ -1358,7 +1327,6 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.allocated() == pool.used() + pool.idle());

Session s5(pool.get());

assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 4);
assertTrue (pool.idle() == 0);
Expand Down Expand Up @@ -1419,13 +1387,10 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.dead() == 0);
assertTrue (pool.allocated() == pool.used() + pool.idle());

s6.setFeature("connected", false);
assertTrue (pool.dead() == 1);

s6.close();
assertTrue (pool.capacity() == 4);
assertTrue (pool.allocated() == 2);
assertTrue (pool.idle() == 0);
assertTrue (pool.allocated() == 3);
assertTrue (pool.idle() == 1);
assertTrue (pool.connTimeout() == 10);
assertTrue (pool.available() == 2);
assertTrue (pool.dead() == 0);
Expand All @@ -1447,7 +1412,9 @@ void SQLExecutor::sessionPool(const std::string& connectString, int minSessions,
assertTrue (pool.connTimeout() == 10);
assertTrue (pool.available() == 0);
assertTrue (pool.dead() == 0);
assertTrue (pool.allocated() == pool.used() + pool.idle());
assertTrue (pool.allocated() == 0);
assertTrue (pool.used() == 0);
assertTrue (pool.idle() == 0);
}
}

Expand Down Expand Up @@ -4214,9 +4181,8 @@ void SQLExecutor::sessionTransaction(const std::string& 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> firstNames;
std::vector<std::string> addresses;
Expand All @@ -4240,10 +4206,13 @@ void SQLExecutor::sessionTransaction(const std::string& connect)
session().setFeature("autoCommit", false);
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_REPEATABLE_READ);
setTransactionIsolation(session(), Session::TRANSACTION_SERIALIZABLE);

setTransactionIsolation(session(), Session::TRANSACTION_READ_COMMITTED);

session().begin();
Expand Down Expand Up @@ -4291,7 +4260,9 @@ void SQLExecutor::sessionTransaction(const std::string& connect)
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assertTrue (2 == count);

// restore the original transaction state
session().setFeature("autoCommit", autoCommit);
setTransactionIsolation(session(), ti);
}


Expand All @@ -4306,6 +4277,9 @@ void SQLExecutor::transaction(const std::string& connect)
Session local("odbc", connect);
local.setFeature("autoCommit", true);

bool autoCommit = session().getFeature("autoCommit");
auto ti = session().getTransactionIsolation();

setTransactionIsolation(session(), Session::TRANSACTION_READ_COMMITTED);
if (local.hasTransactionIsolation(Session::TRANSACTION_READ_UNCOMMITTED))
setTransactionIsolation(local, Session::TRANSACTION_READ_UNCOMMITTED);
Expand All @@ -4329,8 +4303,6 @@ void SQLExecutor::transaction(const std::string& connect)
int count = 0, locCount = 0;
std::string result;

bool autoCommit = session().getFeature("autoCommit");

session().setFeature("autoCommit", true);
assertTrue (!session().isTransaction());
session().setFeature("autoCommit", false);
Expand Down Expand Up @@ -4454,7 +4426,9 @@ void SQLExecutor::transaction(const std::string& connect)
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assertTrue (2 == count);

// restore the original transaction state
session().setFeature("autoCommit", autoCommit);
setTransactionIsolation(session(), ti);
}


Expand Down
12 changes: 6 additions & 6 deletions Data/include/Poco/Data/AbstractSessionImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class AbstractSessionImpl: public SessionImpl
{
}

bool hasFeature(const std::string& name)
bool hasFeature(const std::string& name) const
/// Looks a feature up in the features map
/// and returns true if there is one.
{
Expand All @@ -140,22 +140,22 @@ class AbstractSessionImpl: public SessionImpl
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
/// and calls the feature's getter, if there is one.
{
typename FeatureMap::const_iterator it = _features.find(name);
if (it != _features.end())
{
if (it->second.getter)
return (static_cast<C*>(this)->*it->second.getter)(name);
return (static_cast<const C*>(this)->*it->second.getter)(name);
else
throw NotImplementedException("get", 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
/// and returns true if there is one.
{
Expand All @@ -180,15 +180,15 @@ class AbstractSessionImpl: public SessionImpl
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
/// and calls the property's getter, if there is one.
{
typename PropertyMap::const_iterator it = _properties.find(name);
if (it != _properties.end())
{
if (it->second.getter)
return (static_cast<C*>(this)->*it->second.getter)(name);
return (static_cast<const C*>(this)->*it->second.getter)(name);
else
throw NotImplementedException("set", name);
}
Expand Down
8 changes: 4 additions & 4 deletions Data/include/Poco/Data/PooledSessionImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ class Data_API PooledSessionImpl: public SessionImpl
bool hasTransactionIsolation(Poco::UInt32) const;
bool isTransactionIsolation(Poco::UInt32) 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);
bool getFeature(const std::string& name);
bool hasProperty(const std::string& name);
bool getFeature(const std::string& name) const;
bool hasProperty(const std::string& name) const;
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:
SessionImpl* access() const;
Expand Down
58 changes: 34 additions & 24 deletions Data/include/Poco/Data/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 (%%).
/// 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.
///
/// 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:
static const std::size_t LOGIN_TIMEOUT_DEFAULT = SessionImpl::LOGIN_TIMEOUT_DEFAULT;
Expand All @@ -160,7 +166,7 @@ class Data_API Session
static const Poco::UInt32 TRANSACTION_SERIALIZABLE = 0x00000008L;

Session(Poco::AutoPtr<SessionImpl> ptrImpl);
/// Creates the Session.
/// Creates the Session from SessionImpl.

Session(const std::string& connector,
const std::string& connectionString,
Expand Down Expand Up @@ -221,6 +227,13 @@ class Data_API Session
bool isGood();
/// 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);
/// Sets the session login timeout value.

Expand All @@ -235,12 +248,19 @@ class Data_API Session

void begin();
/// 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();
/// 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();
/// 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();
/// Returns true if session has transaction capabilities.
Expand Down Expand Up @@ -273,7 +293,7 @@ class Data_API Session
/// Utility function that teturns the URI formatted from supplied
/// 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.

void setFeature(const std::string& name, bool state);
Expand All @@ -294,7 +314,7 @@ class Data_API Session
/// Throws a NotSupportedException if the requested feature is
/// 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.

void setProperty(const std::string& name, const Poco::Any& value);
Expand Down Expand Up @@ -322,13 +342,21 @@ class Data_API Session
Session();

Poco::AutoPtr<SessionImpl> _pImpl;
StatementCreator _statementCreator;
StatementCreator _statementCreator;
bool _wasAutoCommit = false;
};


//
// inlines
//

inline bool Session::isAutocommit() const
{
return hasFeature("autoCommit") && getFeature("autoCommit");
}


inline SharedPtr<StatementImpl> Session::createStatementImpl()
{
return _pImpl->createStatementImpl();
Expand Down Expand Up @@ -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()
{
return _pImpl->canTransact();
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down
Loading

0 comments on commit bd06526

Please sign in to comment.