diff --git a/Data/ODBC/src/SessionImpl.cpp b/Data/ODBC/src/SessionImpl.cpp index 365f0c419..563b9b6f2 100644 --- a/Data/ODBC/src/SessionImpl.cpp +++ b/Data/ODBC/src/SessionImpl.cpp @@ -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 : diff --git a/Data/ODBC/testsuite/src/ODBCDB2Test.cpp b/Data/ODBC/testsuite/src/ODBCDB2Test.cpp index f79d1ea40..633cdc1a8 100644 --- a/Data/ODBC/testsuite/src/ODBCDB2Test.cpp +++ b/Data/ODBC/testsuite/src/ODBCDB2Test.cpp @@ -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); diff --git a/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp b/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp index 340c98658..62e3adf27 100644 --- a/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp @@ -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); diff --git a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp index bee9ea036..0db8f21e4 100644 --- a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp @@ -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); diff --git a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp index 6aafef3d7..ddb6c7a2e 100644 --- a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp @@ -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, diff --git a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp index e87771997..fea7debbc 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp @@ -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); diff --git a/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp b/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp index cbaf04bc1..f49d4e037 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp @@ -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); diff --git a/Data/ODBC/testsuite/src/ODBCTest.cpp b/Data/ODBC/testsuite/src/ODBCTest.cpp index e1ce3c8c4..3acc8e452 100644 --- a/Data/ODBC/testsuite/src/ODBCTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCTest.cpp @@ -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."); diff --git a/Data/ODBC/testsuite/src/ODBCTest.h b/Data/ODBC/testsuite/src/ODBCTest.h index 9605b780b..efa5cc5a2 100644 --- a/Data/ODBC/testsuite/src/ODBCTest.h +++ b/Data/ODBC/testsuite/src/ODBCTest.h @@ -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(); diff --git a/Data/ODBC/testsuite/src/SQLExecutor.cpp b/Data/ODBC/testsuite/src/SQLExecutor.cpp index b68d03f72..7c30dfda0 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.cpp +++ b/Data/ODBC/testsuite/src/SQLExecutor.cpp @@ -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 lastNames; - std::vector firstNames; - std::vector addresses; - std::vector 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 lastNames = {"LN1", "LN2"}; + std::vector firstNames = {"FN1", "FN2"}; + std::vector addresses = {"ADDR1", "ADDR2"}; + std::vector 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 lastNames = {"LN1", "LN2"}; + std::vector firstNames = {"FN1", "FN2"}; + std::vector addresses = {"ADDR1", "ADDR2"}; + std::vector 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 lastNames; - std::vector firstNames; - std::vector addresses; - std::vector 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 lastNames = {"LN1", "LN2"}; + std::vector firstNames = {"FN1", "FN2"}; + std::vector addresses = {"ADDR1", "ADDR2"}; + std::vector 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); } diff --git a/Data/ODBC/testsuite/src/SQLExecutor.h b/Data/ODBC/testsuite/src/SQLExecutor.h index 1b6c399ec..18304e816 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.h +++ b/Data/ODBC/testsuite/src/SQLExecutor.h @@ -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(); diff --git a/Data/include/Poco/Data/Session.h b/Data/include/Poco/Data/Session.h index a5747b884..7238c4e9a 100644 --- a/Data/include/Poco/Data/Session.h +++ b/Data/include/Poco/Data/Session.h @@ -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 createStatementImpl();