mirror of
https://github.com/pocoproject/poco.git
synced 2025-03-02 20:30:11 +01:00
fix(Data): transactions are not handled properly #4230
This commit is contained in:
parent
efd9b2ca1d
commit
439acf1924
@ -376,7 +376,7 @@ Poco::UInt32 SessionImpl::getDefaultTransactionIsolation() const
|
||||
Poco::UInt32 SessionImpl::transactionIsolation(SQLULEN isolation)
|
||||
{
|
||||
if (0 == isolation)
|
||||
throw InvalidArgumentException("transactionIsolation(SQLUINTEGER)");
|
||||
throw InvalidArgumentException("transactionIsolation(0): invalid isolation 0");
|
||||
|
||||
Poco::UInt32 ret = 0;
|
||||
|
||||
@ -393,7 +393,7 @@ Poco::UInt32 SessionImpl::transactionIsolation(SQLULEN isolation)
|
||||
ret |= Session::TRANSACTION_SERIALIZABLE;
|
||||
|
||||
if (0 == ret)
|
||||
throw InvalidArgumentException("transactionIsolation(SQLUINTEGER)");
|
||||
throw InvalidArgumentException(Poco::format("transactionIsolation(%u)", isolation));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -401,6 +401,13 @@ Poco::UInt32 SessionImpl::transactionIsolation(SQLULEN isolation)
|
||||
|
||||
void SessionImpl::autoCommit(const std::string&, bool val)
|
||||
{
|
||||
if (val == isAutoCommit()) return;
|
||||
if (val && isTransaction())
|
||||
{
|
||||
throw InvalidAccessException("autoCommit not "
|
||||
"allowed for session in transaction");
|
||||
}
|
||||
|
||||
checkError(Poco::Data::ODBC::SQLSetConnectAttr(_db,
|
||||
SQL_ATTR_AUTOCOMMIT,
|
||||
val ? (SQLPOINTER) SQL_AUTOCOMMIT_ON :
|
||||
|
@ -669,6 +669,9 @@ CppUnit::Test* ODBCDB2Test::suite()
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testMultipleResults);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSQLLogger);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testAutoCommit);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSessionTransactionNoAutoCommit);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testTransactionIsolation);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSessionTransaction);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testTransaction);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testTransactor);
|
||||
|
@ -494,6 +494,9 @@ CppUnit::Test* ODBCMySQLTest::suite()
|
||||
//CppUnit_addTest(pSuite, ODBCMySQLTest, testMultipleResults);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSQLLogger);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testAutoCommit);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSessionTransactionNoAutoCommit);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testTransactionIsolation);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSessionTransaction);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testTransaction);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testTransactor);
|
||||
|
@ -931,6 +931,9 @@ CppUnit::Test* ODBCOracleTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testMultipleResults);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSQLLogger);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testAutoCommit);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSessionTransactionNoAutoCommit);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testTransactionIsolation);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testAutoTransaction);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSessionTransaction);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testTransaction);
|
||||
|
@ -671,6 +671,9 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testMultipleResults);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSQLLogger);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testAutoCommit);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSessionTransactionNoAutoCommit);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTransactionIsolation);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSessionTransaction);
|
||||
// (postgres bug?)
|
||||
// local session claims to be capable of reading uncommitted changes,
|
||||
|
@ -966,6 +966,9 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testMultipleResults);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSQLLogger);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testAutoCommit);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSessionTransactionNoAutoCommit);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransactionIsolation);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSessionTransaction);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransaction);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransactor);
|
||||
|
@ -388,6 +388,8 @@ CppUnit::Test* ODBCSQLiteTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testDynamicAny);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSQLLogger);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testAutoCommit);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testTransactionIsolation);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSessionTransaction);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testTransaction);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testTransactor);
|
||||
|
@ -1206,6 +1206,36 @@ void ODBCTest::testSQLLogger()
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testAutoCommit()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
for (int i = 0; i < 8;)
|
||||
{
|
||||
recreatePersonTable();
|
||||
_pSession->setFeature("autoBind", bindValue(i));
|
||||
_pSession->setFeature("autoExtract", bindValue(i+1));
|
||||
_pExecutor->autoCommit(_rConnectString);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testTransactionIsolation()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
for (int i = 0; i < 8;)
|
||||
{
|
||||
recreatePersonTable();
|
||||
_pSession->setFeature("autoBind", bindValue(i));
|
||||
_pSession->setFeature("autoExtract", bindValue(i+1));
|
||||
_pExecutor->transactionIsolation(_rConnectString);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testSessionTransaction()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
@ -1221,6 +1251,21 @@ void ODBCTest::testSessionTransaction()
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testSessionTransactionNoAutoCommit()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
for (int i = 0; i < 8;)
|
||||
{
|
||||
recreatePersonTable();
|
||||
_pSession->setFeature("autoBind", bindValue(i));
|
||||
_pSession->setFeature("autoExtract", bindValue(i+1));
|
||||
_pExecutor->sessionTransactionNoAutoCommit(_rConnectString);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testTransaction()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
@ -152,7 +152,10 @@ public:
|
||||
virtual void testSQLChannel();
|
||||
virtual void testSQLLogger();
|
||||
|
||||
virtual void testAutoCommit();
|
||||
virtual void testTransactionIsolation();
|
||||
virtual void testSessionTransaction();
|
||||
virtual void testSessionTransactionNoAutoCommit();
|
||||
virtual void testTransaction();
|
||||
virtual void testTransactor();
|
||||
virtual void testNullable();
|
||||
|
@ -4172,40 +4172,23 @@ void SQLExecutor::setTransactionIsolation(Session& session, Poco::UInt32 ti)
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::sessionTransaction(const std::string& connect)
|
||||
void SQLExecutor::autoCommit(const std::string& connect)
|
||||
{
|
||||
if (!session().canTransact())
|
||||
{
|
||||
std::cout << "Session not capable of transactions." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
Session local("odbc", connect);
|
||||
|
||||
std::string funct = "sessionTransaction()";
|
||||
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;
|
||||
|
||||
bool autoCommit = session().getFeature("autoCommit");
|
||||
|
||||
session().setFeature("autoCommit", true);
|
||||
assertTrue (!session().isTransaction());
|
||||
session().setFeature("autoCommit", false);
|
||||
assertTrue (!session().isTransaction());
|
||||
session().setFeature("autoCommit", true);
|
||||
assertTrue (!session().isTransaction());
|
||||
|
||||
session().setFeature("autoCommit", autoCommit);
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::transactionIsolation(const std::string& connect)
|
||||
{
|
||||
auto ti = session().getTransactionIsolation();
|
||||
|
||||
// these are just calls to check the transactional capabilities of the session
|
||||
@ -4215,18 +4198,52 @@ void SQLExecutor::sessionTransaction(const std::string& connect)
|
||||
setTransactionIsolation(session(), Session::TRANSACTION_SERIALIZABLE);
|
||||
setTransactionIsolation(session(), Session::TRANSACTION_READ_COMMITTED);
|
||||
|
||||
setTransactionIsolation(session(), ti);
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::sessionTransaction(const std::string& connect)
|
||||
{
|
||||
if (!session().canTransact())
|
||||
{
|
||||
std::cout << "Session not capable of transactions." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
bool autoCommit = session().getFeature("autoCommit");
|
||||
|
||||
Session local("odbc", connect);
|
||||
|
||||
std::string funct = "sessionTransaction()";
|
||||
|
||||
std::string tableName("Person");
|
||||
std::vector<std::string> lastNames = {"LN1", "LN2"};
|
||||
std::vector<std::string> firstNames = {"FN1", "FN2"};
|
||||
std::vector<std::string> addresses = {"ADDR1", "ADDR2"};
|
||||
std::vector<int> ages = {1, 2};
|
||||
int count = 0, locCount = 0;
|
||||
std::string result;
|
||||
|
||||
session().setFeature("autoCommit", true);
|
||||
session().begin();
|
||||
assertTrue (session().isTransaction());
|
||||
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
|
||||
// autocommit is invalid for session in transaction ...
|
||||
try
|
||||
{
|
||||
session().setFeature("autoCommit", true);
|
||||
fail ("must fail on autocommit setting during transaction");
|
||||
}
|
||||
catch(const Poco::InvalidAccessException& e) { }
|
||||
// but setting it to its current state is allowed (no-op)
|
||||
session().setFeature("autoCommit", false);
|
||||
|
||||
session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
|
||||
assertTrue (session().isTransaction());
|
||||
|
||||
Statement stmt = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
|
||||
|
||||
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "SELECT COUNT(*) FROM Person", into(count), now;
|
||||
assertTrue (2 == count);
|
||||
assertTrue (session().isTransaction());
|
||||
session().rollback();
|
||||
@ -4234,35 +4251,111 @@ void SQLExecutor::sessionTransaction(const std::string& connect)
|
||||
|
||||
stmt.wait();
|
||||
assertTrue (0 == locCount);
|
||||
stmt.reset(session());
|
||||
|
||||
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "SELECT count(*) FROM Person", into(count), now;
|
||||
assertTrue (0 == count);
|
||||
assertTrue (!session().isTransaction());
|
||||
|
||||
session().begin();
|
||||
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
|
||||
assertTrue (session().isTransaction());
|
||||
|
||||
Statement stmt1 = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
|
||||
stmt = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
|
||||
|
||||
session().commit();
|
||||
assertTrue (!session().isTransaction());
|
||||
|
||||
stmt1.wait();
|
||||
stmt.wait();
|
||||
assertTrue (2 == locCount);
|
||||
|
||||
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "SELECT count(*) FROM Person", into(count), now;
|
||||
assertTrue (2 == count);
|
||||
// end autoCommit = true
|
||||
|
||||
// restore the original transaction state
|
||||
session().setFeature("autoCommit", autoCommit);
|
||||
setTransactionIsolation(session(), ti);
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::sessionTransactionNoAutoCommit(const std::string& connect)
|
||||
{
|
||||
bool autoCommit = session().getFeature("autoCommit");
|
||||
|
||||
Session local("odbc", connect);
|
||||
local.setFeature("autoCommit", false);
|
||||
assertTrue (!local.getFeature("autoCommit"));
|
||||
|
||||
if (!local.canTransact())
|
||||
{
|
||||
std::cout << "Session not capable of transactions." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string funct = "sessionTransactionNoAutoCommit()";
|
||||
std::vector<std::string> lastNames = {"LN1", "LN2"};
|
||||
std::vector<std::string> firstNames = {"FN1", "FN2"};
|
||||
std::vector<std::string> addresses = {"ADDR1", "ADDR2"};
|
||||
std::vector<int> ages = {1, 2};
|
||||
std::string tableName("Person");
|
||||
int count = 0, locCount = 0;
|
||||
std::string result;
|
||||
|
||||
// no autoCommit session becomes transaction without explicit begin()
|
||||
assertTrue (!local.isTransaction());
|
||||
assertTrue (!session().isTransaction());
|
||||
local << "INSERT INTO Person VALUES (?,?,?,?)",
|
||||
use(lastNames), use(firstNames), use(addresses), use(ages), now;
|
||||
Statement stmt = (session() << "SELECT COUNT(*) FROM Person",
|
||||
into(count), async, now);
|
||||
local << "SELECT COUNT(*) FROM Person", into(locCount), now;
|
||||
assertTrue (0 == count);
|
||||
assertTrue (2 == locCount);
|
||||
assertTrue (local.isTransaction());
|
||||
|
||||
// autocommit is invalid for session in transaction ...
|
||||
try
|
||||
{
|
||||
local.setFeature("autoCommit", true);
|
||||
fail ("must fail on autocommit setting during transaction");
|
||||
}
|
||||
catch(const Poco::InvalidAccessException& e) { }
|
||||
// but setting it to its current state is allowed (no-op)
|
||||
local.setFeature("autoCommit", false);
|
||||
|
||||
assertTrue (!session().isTransaction());
|
||||
|
||||
local.commit();
|
||||
assertTrue (!local.isTransaction());
|
||||
|
||||
stmt.wait();
|
||||
assertTrue (2 == count);
|
||||
count = 0;
|
||||
stmt.reset(session());
|
||||
|
||||
assertTrue (!local.isTransaction());
|
||||
assertTrue (!session().isTransaction());
|
||||
local << "INSERT INTO Person VALUES (?,?,?,?)",
|
||||
use(lastNames), use(firstNames), use(addresses), use(ages), now;
|
||||
stmt = (session() << "SELECT COUNT(*) FROM Person", into(count), async, now);
|
||||
local << "SELECT COUNT(*) FROM Person", into(locCount), now;
|
||||
assertTrue (0 == count);
|
||||
assertTrue (4 == locCount);
|
||||
assertTrue (local.isTransaction());
|
||||
assertTrue (!session().isTransaction());
|
||||
|
||||
local.rollback();
|
||||
assertTrue (!local.isTransaction());
|
||||
stmt.wait();
|
||||
assertTrue (2 == count);
|
||||
|
||||
locCount = 0;
|
||||
session() << "SELECT COUNT(*) FROM Person", into(count), now;
|
||||
local << "SELECT COUNT(*) FROM Person", into(locCount), now;
|
||||
assertTrue (2 == count);
|
||||
assertTrue (2 == locCount);
|
||||
|
||||
session().setFeature("autoCommit", autoCommit);
|
||||
}
|
||||
|
||||
|
||||
@ -4287,19 +4380,11 @@ void SQLExecutor::transaction(const std::string& connect)
|
||||
setTransactionIsolation(local, 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);
|
||||
std::vector<std::string> lastNames = {"LN1", "LN2"};
|
||||
std::vector<std::string> firstNames = {"FN1", "FN2"};
|
||||
std::vector<std::string> addresses = {"ADDR1", "ADDR2"};
|
||||
std::vector<int> ages = {1, 2};
|
||||
int count = 0, locCount = 0;
|
||||
std::string result;
|
||||
|
||||
@ -4334,7 +4419,8 @@ void SQLExecutor::transaction(const std::string& connect)
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
assertTrue (0 == count);
|
||||
assertTrue (!session().isTransaction());
|
||||
assertTrue (session().isTransaction());
|
||||
session().commit();
|
||||
|
||||
{
|
||||
Transaction trans(session());
|
||||
@ -4394,14 +4480,10 @@ void SQLExecutor::transaction(const std::string& connect)
|
||||
Transaction trans(session());
|
||||
|
||||
trans.execute(sql1, false);
|
||||
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "SELECT count(*) FROM Person", into(count), now;
|
||||
assertTrue (1 == count);
|
||||
trans.execute(sql2, false);
|
||||
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "SELECT count(*) FROM Person", into(count), now;
|
||||
assertTrue (2 == count);
|
||||
|
||||
Statement stmt2 = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
|
||||
@ -4425,6 +4507,7 @@ void SQLExecutor::transaction(const std::string& connect)
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
assertTrue (2 == count);
|
||||
session().commit();
|
||||
|
||||
// restore the original transaction state
|
||||
session().setFeature("autoCommit", autoCommit);
|
||||
@ -4457,24 +4540,20 @@ void SQLExecutor::transactor()
|
||||
int count = 0;
|
||||
|
||||
bool autoCommit = session().getFeature("autoCommit");
|
||||
auto ti = session().getTransactionIsolation();
|
||||
|
||||
session().setFeature("autoCommit", false);
|
||||
session().setTransactionIsolation(Session::TRANSACTION_READ_COMMITTED);
|
||||
|
||||
TestCommitTransactor ct;
|
||||
Transaction t1(session(), ct);
|
||||
|
||||
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "SELECT count(*) FROM Person", into(count), now;
|
||||
assertTrue (1 == count);
|
||||
|
||||
try { session() << "DELETE FROM Person", now; session().commit();}
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "DELETE FROM Person", now; session().commit();
|
||||
|
||||
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "SELECT count(*) FROM Person", into(count), now;
|
||||
assertTrue (0 == count);
|
||||
|
||||
try
|
||||
@ -4484,9 +4563,7 @@ void SQLExecutor::transactor()
|
||||
fail ("must fail");
|
||||
} catch (Poco::Exception&) { }
|
||||
|
||||
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "SELECT count(*) FROM Person", into(count), now;
|
||||
assertTrue (0 == count);
|
||||
|
||||
try
|
||||
@ -4497,9 +4574,7 @@ void SQLExecutor::transactor()
|
||||
fail ("must fail");
|
||||
} catch (Poco::Exception&) { }
|
||||
|
||||
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "SELECT count(*) FROM Person", into(count), now;
|
||||
assertTrue (0 == count);
|
||||
|
||||
try
|
||||
@ -4510,9 +4585,7 @@ void SQLExecutor::transactor()
|
||||
fail ("must fail");
|
||||
} catch (Poco::Exception&) { }
|
||||
|
||||
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "SELECT count(*) FROM Person", into(count), now;
|
||||
assertTrue (0 == count);
|
||||
|
||||
try
|
||||
@ -4523,12 +4596,13 @@ void SQLExecutor::transactor()
|
||||
fail ("must fail");
|
||||
} catch (Poco::Exception&) { }
|
||||
|
||||
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
session() << "SELECT count(*) FROM Person", into(count), now;
|
||||
assertTrue (0 == count);
|
||||
session().commit();
|
||||
|
||||
// restore the original transaction state
|
||||
session().setFeature("autoCommit", autoCommit);
|
||||
setTransactionIsolation(session(), ti);
|
||||
}
|
||||
|
||||
|
||||
|
@ -511,7 +511,11 @@ public:
|
||||
void sqlChannel(const std::string& connect);
|
||||
void sqlLogger(const std::string& connect);
|
||||
|
||||
void autoCommit(const std::string& connect);
|
||||
void transactionIsolation(const std::string& connect);
|
||||
|
||||
void sessionTransaction(const std::string& connect);
|
||||
void sessionTransactionNoAutoCommit(const std::string& connect);
|
||||
void transaction(const std::string& connect);
|
||||
void transactor();
|
||||
void nullable();
|
||||
|
@ -201,7 +201,10 @@ public:
|
||||
Statement operator << (const T& t)
|
||||
/// Creates a Statement with the given data as SQLContent
|
||||
{
|
||||
return _statementCreator << t;
|
||||
Statement stmt = (_statementCreator << t);
|
||||
if (!_pImpl->isTransaction() && !isAutocommit())
|
||||
_pImpl->begin();
|
||||
return stmt;
|
||||
}
|
||||
|
||||
SharedPtr<StatementImpl> createStatementImpl();
|
||||
|
Loading…
x
Reference in New Issue
Block a user