diff --git a/Data/ODBC/Makefile b/Data/ODBC/Makefile index dcf6550da..9be4700cf 100644 --- a/Data/ODBC/Makefile +++ b/Data/ODBC/Makefile @@ -12,8 +12,9 @@ objects = Binder ConnectionHandle Connector EnvironmentHandle \ Extractor ODBCException ODBCMetaColumn ODBCStatementImpl \ Parameter Preparator SessionImpl TypeInfo Unicode Utility +target_includes = $(POCO_BASE)/Data/testsuite/include ifndef POCO_DATA_NO_SQL_PARSER - target_includes = $(POCO_BASE)/Data/src + target_includes += $(POCO_BASE)/Data/src endif target = PocoDataODBC diff --git a/Data/ODBC/include/Poco/Data/ODBC/ODBCException.h b/Data/ODBC/include/Poco/Data/ODBC/ODBCException.h index e8efa451f..098ffde95 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/ODBCException.h +++ b/Data/ODBC/include/Poco/Data/ODBC/ODBCException.h @@ -138,10 +138,10 @@ private: }; -typedef HandleException EnvironmentException; -typedef HandleException ConnectionException; -typedef HandleException StatementException; -typedef HandleException DescriptorException; +using EnvironmentException = HandleException; +using ConnectionException = HandleException; +using StatementException = HandleException; +using DescriptorException = HandleException; } } } // namespace Poco::Data::ODBC diff --git a/Data/ODBC/testsuite/Makefile b/Data/ODBC/testsuite/Makefile index 9472978b2..0dd949e48 100644 --- a/Data/ODBC/testsuite/Makefile +++ b/Data/ODBC/testsuite/Makefile @@ -33,12 +33,13 @@ ifeq ($(POCO_CONFIG),MinGW) objects += ODBCAccessTest endif +target_includes = $(POCO_BASE)/Data/testsuite/include ifndef POCO_DATA_NO_SQL_PARSER - target_includes = $(POCO_BASE)/Data/src + target_includes += $(POCO_BASE)/Data/src endif target = testrunner target_version = 1 -target_libs = PocoDataODBC PocoData PocoFoundation CppUnit +target_libs = PocoDataODBC PocoDataTest PocoData PocoFoundation CppUnit include $(POCO_BASE)/build/rules/exec diff --git a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp index af0d85fd5..5d3ef3874 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp @@ -189,7 +189,7 @@ void ODBCSQLServerTest::testBLOB() try { executor().blob(maxFldSize, "CONVERT(VARBINARY(MAX),?)"); - fail ("must fail"); + fail (__func__, __LINE__, __FILE__); } catch (DataException&) { @@ -209,7 +209,7 @@ void ODBCSQLServerTest::testBLOB() try { executor().blob(maxFldSize+1, "CONVERT(VARBINARY(MAX),?)"); - fail ("must fail"); + fail (__func__, __LINE__, __FILE__); } catch (DataException&) { } } diff --git a/Data/ODBC/testsuite/src/ODBCTest.cpp b/Data/ODBC/testsuite/src/ODBCTest.cpp index 7aa3d4233..5cd3e47f6 100644 --- a/Data/ODBC/testsuite/src/ODBCTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCTest.cpp @@ -55,7 +55,7 @@ const bool ODBCTest::_bindValues[8] = ODBCTest::ODBCTest(const std::string& name, SessionPtr pSession, - ExecPtr pExecutor, + ExecPtr pExecutor, std::string& rDSN, std::string& rUID, std::string& rPwd, diff --git a/Data/ODBC/testsuite/src/ODBCTest.h b/Data/ODBC/testsuite/src/ODBCTest.h index 31a7d1ade..ba6a6a86c 100644 --- a/Data/ODBC/testsuite/src/ODBCTest.h +++ b/Data/ODBC/testsuite/src/ODBCTest.h @@ -23,14 +23,14 @@ #include "SQLExecutor.h" -#define POCO_ODBC_TEST_DATABASE_SERVER "localhost" +#define POCO_ODBC_TEST_DATABASE_SERVER "10.211.55.5"//"localhost" class ODBCTest: public CppUnit::TestCase { public: - typedef Poco::SharedPtr SessionPtr; - typedef Poco::SharedPtr ExecPtr; + using SessionPtr = Poco::SharedPtr; + using ExecPtr = Poco::SharedPtr; ODBCTest(const std::string& name, SessionPtr pSession, diff --git a/Data/ODBC/testsuite/src/SQLExecutor.cpp b/Data/ODBC/testsuite/src/SQLExecutor.cpp index 2e48676a0..75b22ba1c 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.cpp +++ b/Data/ODBC/testsuite/src/SQLExecutor.cpp @@ -102,188 +102,6 @@ using Poco::UnicodeConverter; using Poco::UTF16String; using Poco::UTF32String; -struct Person -{ - std::string lastName; - std::string firstName; - std::string address; - int age; - Person(){age = 0;} - Person(const std::string& ln, const std::string& fn, const std::string& adr, int a):lastName(ln), firstName(fn), address(adr), age(a) - { - } - bool operator==(const Person& other) const - { - return lastName == other.lastName && firstName == other.firstName && address == other.address && age == other.age; - } - - bool operator < (const Person& p) const - { - if (age < p.age) - return true; - if (lastName < p.lastName) - return true; - if (firstName < p.firstName) - return true; - return (address < p.address); - } - - const std::string& operator () () const - /// This method is required so we can extract data to a map! - { - // we choose the lastName as the key - return lastName; - } -}; - - -struct RefCountedPerson : public Poco::RefCountedObject -{ - std::string lastName; - std::string firstName; - std::string address; - int age; - RefCountedPerson(){age = 0;} - RefCountedPerson(const std::string& ln, const std::string& fn, const std::string& adr, int a):lastName(ln), firstName(fn), address(adr), age(a) - { - } - bool operator==(const Person& other) const - { - return lastName == other.lastName && firstName == other.firstName && address == other.address && age == other.age; - } - - bool operator < (const RefCountedPerson& p) const - { - if (age < p.age) - return true; - if (lastName < p.lastName) - return true; - if (firstName < p.firstName) - return true; - return (address < p.address); - } - - const std::string& operator () () const - /// This method is required so we can extract data to a map! - { - // we choose the lastName as the key - return lastName; - } - -private: - RefCountedPerson(const RefCountedPerson &); - RefCountedPerson& operator = (const RefCountedPerson&); -}; - - -namespace Poco { -namespace Data { - - -template <> -class TypeHandler -{ -public: - static void bind(std::size_t pos, - const Person& obj, - AbstractBinder::Ptr pBinder, - AbstractBinder::Direction dir = AbstractBinder::PD_IN) - { - // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3)) - poco_assert_dbg (!pBinder.isNull()); - pBinder->bind(pos++, obj.lastName, dir); - pBinder->bind(pos++, obj.firstName, dir); - pBinder->bind(pos++, obj.address, dir); - pBinder->bind(pos++, obj.age, dir); - } - - static void prepare(std::size_t pos, const Person& obj, AbstractPreparator::Ptr pPrepare) - { - // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3)) - poco_assert_dbg (!pPrepare.isNull()); - pPrepare->prepare(pos++, obj.lastName); - pPrepare->prepare(pos++, obj.firstName); - pPrepare->prepare(pos++, obj.address); - pPrepare->prepare(pos++, obj.age); - } - - static std::size_t size() - { - return 4; - } - - static void extract(std::size_t pos, Person& obj, const Person& defVal, AbstractExtractor::Ptr pExt) - { - poco_assert_dbg (!pExt.isNull()); - if (!pExt->extract(pos++, obj.lastName)) - obj.lastName = defVal.lastName; - if (!pExt->extract(pos++, obj.firstName)) - obj.firstName = defVal.firstName; - if (!pExt->extract(pos++, obj.address)) - obj.address = defVal.address; - if (!pExt->extract(pos++, obj.age)) - obj.age = defVal.age; - } - -private: - TypeHandler(const TypeHandler&); - TypeHandler& operator=(const TypeHandler&); -}; - - -template <> -class TypeHandler -{ -public: - static void bind(std::size_t pos, - const RefCountedPerson& obj, - AbstractBinder::Ptr pBinder, - AbstractBinder::Direction dir = AbstractBinder::PD_IN) - { - // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3)) - poco_assert_dbg (!pBinder.isNull()); - pBinder->bind(pos++, obj.lastName, dir); - pBinder->bind(pos++, obj.firstName, dir); - pBinder->bind(pos++, obj.address, dir); - pBinder->bind(pos++, obj.age, dir); - } - - static void prepare(std::size_t pos, RefCountedPerson& obj, AbstractPreparator::Ptr pPrepare) - { - // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3)) - poco_assert_dbg (!pPrepare.isNull()); - pPrepare->prepare(pos++, obj.lastName); - pPrepare->prepare(pos++, obj.firstName); - pPrepare->prepare(pos++, obj.address); - pPrepare->prepare(pos++, obj.age); - } - - static std::size_t size() - { - return 4; - } - - static void extract(std::size_t pos, RefCountedPerson& obj, const RefCountedPerson& defVal, AbstractExtractor::Ptr pExt) - { - poco_assert_dbg (!pExt.isNull()); - if (!pExt->extract(pos++, obj.lastName)) - obj.lastName = defVal.lastName; - if (!pExt->extract(pos++, obj.firstName)) - obj.firstName = defVal.firstName; - if (!pExt->extract(pos++, obj.address)) - obj.address = defVal.address; - if (!pExt->extract(pos++, obj.age)) - obj.age = defVal.age; - } - -private: - TypeHandler(const TypeHandler&); - TypeHandler& operator=(const TypeHandler&); -}; - - -} } // namespace Poco::Data - const std::string SQLExecutor::MULTI_INSERT = "INSERT INTO Test VALUES ('1', 2, 3.5);" @@ -303,7 +121,8 @@ const std::string SQLExecutor::MULTI_SELECT = SQLExecutor::SQLExecutor(const std::string& name, Poco::Data::Session* pSession, Poco::Data::Session* pEncSession): CppUnit::TestCase(name), _pSession(pSession), - _pEncSession(pEncSession) + _pEncSession(pEncSession), + _dataExecutor("Poco::Data SQL Executor", pSession, pEncSession) { } @@ -313,6 +132,21 @@ SQLExecutor::~SQLExecutor() } +Poco::Data::Session& SQLExecutor::session(bool enc) +{ + if (!enc) + { + poco_check_ptr(_pSession); + return *_pSession; + } + else + { + poco_check_ptr(_pEncSession); + return *_pEncSession; + } +} + + void SQLExecutor::bareboneODBCTest(const std::string& dbConnString, const std::string& tableCreateString, SQLExecutor::DataBinding bindMode, @@ -1147,30 +981,7 @@ void SQLExecutor::execute(const std::string& sql) void SQLExecutor::connection(const std::string& connectString) { Poco::Data::ODBC::Connection c; - assertFalse (c.isConnected()); - assertTrue (c.connect(connectString, 5)); - assertTrue (c.isConnected()); - assertTrue (c.getTimeout() == 5); - c.setTimeout(6); - assertTrue (c.getTimeout() == 6); - assertTrue (c.disconnect()); - assertFalse (c.isConnected()); - assertTrue (c.connect(connectString)); - assertTrue (c.isConnected()); - try - { - c.connect(); - fail ("Connection attempt must fail when already connected"); - } - catch(const Poco::InvalidAccessException&){} - assertTrue (c.disconnect()); - assertFalse (c.isConnected()); - try - { - c.connect(); - fail ("Connection attempt with empty string must fail"); - } - catch(const Poco::InvalidArgumentException&){} + _dataExecutor.connection(c, connectString); } @@ -1214,2394 +1025,13 @@ void SQLExecutor::session(const std::string& connectString, int timeout) } -void SQLExecutor::sessionPool(const std::string& connectString, int minSessions, int maxSessions, int idleTime, int timeout) -{ - assertTrue (minSessions <= maxSessions); - - SessionPool sp("ODBC", connectString, minSessions, maxSessions, idleTime, timeout); - assertEqual (0, sp.allocated()); - assertEqual (maxSessions, sp.available()); - Session s1 = sp.get(); - assertEqual (minSessions, sp.allocated()); - assertEqual (maxSessions-1, sp.available()); - s1 = sp.get(); - assertEqual (2, sp.allocated()); - assertEqual (maxSessions-1, sp.available()); - { - Session s2 = sp.get(); - assertEqual (2, sp.allocated()); - assertEqual (maxSessions-2, sp.available()); - } - assertEqual (2, sp.allocated()); - assertEqual (maxSessions-1, sp.available()); - - Thread::sleep(idleTime + 500); - assertEqual (maxSessions-minSessions, sp.available()); - - try - { - sp.setFeature("autoBind", true); - fail("SessionPool must throw on setFeature after the first session was created."); - } - catch(const Poco::InvalidAccessException&) {} - try - { - sp.setProperty("handle", SQL_NULL_HDBC); - fail("SessionPool must throw on setProperty after the first session was created."); - } - catch(const Poco::InvalidAccessException&) {} - - std::vector sessions; - for (int i = 0; i < maxSessions-minSessions; ++i) - { - sessions.push_back(sp.get()); - } - - try - { - Session s = sp.get(); - fail("SessionPool must throw when no sesions available."); - } - catch(const Poco::Data::SessionPoolExhaustedException&) {} - - sp.shutdown(); - try - { - Session s = sp.get(); - fail("SessionPool that was shut down must throw on get."); - } - catch(const Poco::InvalidAccessException&) {} - - { - SessionPool pool("ODBC", connectString, 1, 4, 2, 10); - - try { pool.getFeature("g1"); fail ("getting an unsuported feature must fail"); } - catch ( Poco::NotFoundException& ) { } - - try { pool.getProperty("r1"); fail ("getting an unsuported property must fail"); } - catch ( Poco::NotFoundException& ) { } - - assertTrue (pool.capacity() == 4); - assertTrue (pool.allocated() == 0); - assertTrue (pool.idle() == 0); - assertTrue (pool.connTimeout() == 10); - assertTrue (pool.available() == 4); - assertTrue (pool.dead() == 0); - assertTrue (pool.allocated() == pool.used() + pool.idle()); - Session s1(pool.get()); - - try { pool.setFeature("f1", true); fail ("setting an unsuported feature must fail"); } - catch (Poco::InvalidAccessException&) { } - catch (Poco::NotImplementedException&) { } - catch (Poco::Data::NotSupportedException&) { } - - 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); - assertTrue (pool.idle() == 0); - assertTrue (pool.connTimeout() == 10); - assertTrue (pool.available() == 3); - assertTrue (pool.dead() == 0); - assertTrue (pool.allocated() == pool.used() + pool.idle()); - - Session s2(pool.get()); - assertTrue (pool.capacity() == 4); - assertTrue (pool.allocated() == 2); - assertTrue (pool.idle() == 0); - assertTrue (pool.connTimeout() == 10); - assertTrue (pool.available() == 2); - assertTrue (pool.dead() == 0); - assertTrue (pool.allocated() == pool.used() + pool.idle()); - - Session s4(pool.get()); - 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()); - - Session s5(pool.get()); - assertTrue (pool.capacity() == 4); - assertTrue (pool.allocated() == 4); - assertTrue (pool.idle() == 0); - assertTrue (pool.connTimeout() == 10); - assertTrue (pool.available() == 0); - assertTrue (pool.dead() == 0); - assertTrue (pool.allocated() == pool.used() + pool.idle()); - - try - { - Session s6(pool.get()); - fail("pool exhausted - must throw"); - } - catch (Poco::Data::SessionPoolExhaustedException&) { } - - s5.close(); - assertTrue (pool.capacity() == 4); - assertTrue (pool.allocated() == 4); - assertTrue (pool.idle() == 1); - assertTrue (pool.connTimeout() == 10); - assertTrue (pool.available() == 1); - assertTrue (pool.dead() == 0); - assertTrue (pool.allocated() == pool.used() + pool.idle()); - - try - { - s5 << "DROP TABLE IF EXISTS Test", now; - fail("session unusable - must throw"); - } - catch (Poco::Data::SessionUnavailableException&) { } - - s4.close(); - assertTrue (pool.capacity() == 4); - assertTrue (pool.allocated() == 4); - assertTrue (pool.idle() == 2); - assertTrue (pool.connTimeout() == 10); - assertTrue (pool.available() == 2); - assertTrue (pool.dead() == 0); - assertTrue (pool.allocated() == pool.used() + pool.idle()); - - Thread::sleep(5000); // time to clean up idle sessions - - assertTrue (pool.capacity() == 4); - assertTrue (pool.allocated() == 2); - assertTrue (pool.idle() == 0); - assertTrue (pool.connTimeout() == 10); - assertTrue (pool.available() == 2); - assertTrue (pool.dead() == 0); - assertTrue (pool.allocated() == pool.used() + pool.idle()); - - Session s6(pool.get()); - - 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()); - - s6.close(); - 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()); - - assertTrue (pool.isActive()); - pool.shutdown(); - assertTrue (!pool.isActive()); - try - { - Session s7(pool.get()); - fail("pool shut down - must throw"); - } - catch (InvalidAccessException&) { } - - assertTrue (pool.capacity() == 4); - assertTrue (pool.allocated() == 0); - assertTrue (pool.idle() == 0); - assertTrue (pool.connTimeout() == 10); - assertTrue (pool.available() == 0); - assertTrue (pool.dead() == 0); - assertTrue (pool.allocated() == 0); - assertTrue (pool.used() == 0); - assertTrue (pool.idle() == 0); - } -} - - -void SQLExecutor::zeroRows() -{ - Statement stmt = (session() << "SELECT * FROM Person WHERE 0 = 1"); - assertTrue (0 == stmt.execute()); -} - - -void SQLExecutor::simpleAccess() -{ - std::string funct = "simpleAccess()"; - std::string lastName = "lastName"; - std::string firstName("firstName"); - std::string address("Address"); - int age = 133132; - int count = 0; - std::string result; - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - count = 0; - 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); } - assertTrue (count == 1); - - try { session() << "SELECT LastName FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (lastName == result); - - try { session() << "SELECT Age 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); } - assertTrue (count == age); -} - - -void SQLExecutor::complexType() -{ - std::string funct = "complexType()"; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(p1), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(p2), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - 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); } - assertTrue (count == 2); - - Person c1; - try { session() << "SELECT * FROM Person WHERE LastName = 'LN1'", into(c1), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (c1 == p1); -} - - -void SQLExecutor::complexTypeTuple() -{ - std::string funct = "complexTypeTuple()"; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - - Tuple t(p1,p2); - try { *_pSession << "INSERT INTO Person VALUES(?,?,?,?,?,?,?,?)", use(t), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - Tuple ret; - assertTrue (ret != t); - try { *_pSession << "SELECT * FROM Person", into(ret), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (ret == t); -} - - -void SQLExecutor::simpleAccessVector() -{ - std::string funct = "simpleAccessVector()"; - 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; - std::string result; - - 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); } - - 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); } - assertTrue (count == 2); - - std::vector lastNamesR; - std::vector firstNamesR; - std::vector addressesR; - std::vector agesR; - try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (ages == agesR); - assertTrue (lastNames == lastNamesR); - assertTrue (firstNames == firstNamesR); - assertTrue (addresses == addressesR); -} - - -void SQLExecutor::complexTypeVector() -{ - std::string funct = "complexTypeVector()"; - std::vector people; - people.push_back(Person("LN1", "FN1", "ADDR1", 1)); - people.push_back(Person("LN2", "FN2", "ADDR2", 2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - 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); } - assertTrue (count == 2); - - std::vector result; - try { session() << "SELECT * FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result == people); -} - - -void SQLExecutor::sharedPtrComplexTypeVector() -{ - std::string funct = "sharedPtrComplexTypeVector()"; - std::vector > people; - people.push_back(new Person("LN1", "FN1", "ADDR1", 1)); - people.push_back(new Person("LN2", "FN2", "ADDR2", 2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - 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); } - assertTrue (count == 2); - - std::vector result; - try { session() << "SELECT * FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (2 == result.size()); - assertTrue (result[0] == *people[0]); - assertTrue (result[1] == *people[1]); -} - - -void SQLExecutor::autoPtrComplexTypeVector() -{ - std::string funct = "sharedPtrComplexTypeVector()"; - std::vector > people; - people.push_back(new RefCountedPerson("LN1", "FN1", "ADDR1", 1)); - people.push_back(new RefCountedPerson("LN2", "FN2", "ADDR2", 2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - 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); } - assertTrue (count == 2); - - std::vector result; - try { session() << "SELECT * FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (2 == result.size()); - assertTrue (result[0].address == people[0]->address); - assertTrue (result[0].age == people[0]->age); - assertTrue (result[0].firstName == people[0]->firstName); - assertTrue (result[0].lastName == people[0]->lastName); - assertTrue (result[1].address == people[1]->address); - assertTrue (result[1].age == people[1]->age); - assertTrue (result[1].firstName == people[1]->firstName); - assertTrue (result[1].lastName == people[1]->lastName); -} - - -void SQLExecutor::insertVector() -{ - std::string funct = "insertVector()"; - std::vector str; - str.push_back("s1"); - str.push_back("s2"); - str.push_back("s3"); - str.push_back("s3"); - int count = 100; - - { - Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(str))); - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 0); - - try { stmt.execute(); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 4); - } - count = 0; - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 4); -} - - -void SQLExecutor::insertEmptyVector() -{ - std::string funct = "insertEmptyVector()"; - std::vector str; - - try - { - session() << "INSERT INTO Strings VALUES (?)", use(str), now; - fail("empty collections should not work"); - } - catch (Poco::Exception&) - { - } -} - - -void SQLExecutor::simpleAccessList() -{ - std::string funct = "simpleAccessList()"; - std::list lastNames; - std::list firstNames; - std::list addresses; - std::list 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; - std::string result; - - 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); } - - 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); } - assertTrue (count == 2); - - std::list lastNamesR; - std::list firstNamesR; - std::list addressesR; - std::list agesR; - try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (ages == agesR); - assertTrue (lastNames == lastNamesR); - assertTrue (firstNames == firstNamesR); - assertTrue (addresses == addressesR); -} - - -void SQLExecutor::complexTypeList() -{ - std::string funct = "complexTypeList()"; - std::list people; - people.push_back(Person("LN1", "FN1", "ADDR1", 1)); - people.push_back(Person("LN2", "FN2", "ADDR2", 2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - 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); } - assertTrue (count == 2); - - std::list result; - try { session() << "SELECT * FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result == people); -} - - -void SQLExecutor::insertList() -{ - std::string funct = "insertList()"; - std::list str; - str.push_back("s1"); - str.push_back("s2"); - str.push_back("s3"); - str.push_back("s3"); - int count = 100; - - { - Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(str))); - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 0); - - try { stmt.execute(); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 4); - } - count = 0; - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 4); -} - - -void SQLExecutor::insertEmptyList() -{ - std::string funct = "insertEmptyList()"; - std::list str; - - try - { - session() << "INSERT INTO Strings VALUES (?)", use(str), now; - fail("empty collections should not work"); - } - catch (Poco::Exception&) - { - } -} - - -void SQLExecutor::simpleAccessDeque() -{ - std::string funct = "simpleAccessDeque()"; - std::deque lastNames; - std::deque firstNames; - std::deque addresses; - std::deque 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; - std::string result; - - 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); } - - 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); } - assertTrue (count == 2); - - std::deque lastNamesR; - std::deque firstNamesR; - std::deque addressesR; - std::deque agesR; - try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (ages == agesR); - assertTrue (lastNames == lastNamesR); - assertTrue (firstNames == firstNamesR); - assertTrue (addresses == addressesR); -} - - -void SQLExecutor::complexTypeDeque() -{ - std::string funct = "complexTypeDeque()"; - std::deque people; - people.push_back(Person("LN1", "FN1", "ADDR1", 1)); - people.push_back(Person("LN2", "FN2", "ADDR2", 2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - 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); } - assertTrue (count == 2); - - std::deque result; - try { session() << "SELECT * FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result == people); -} - - -void SQLExecutor::insertDeque() -{ - std::string funct = "insertDeque()"; - std::deque str; - str.push_back("s1"); - str.push_back("s2"); - str.push_back("s3"); - str.push_back("s3"); - int count = 100; - - { - Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(str))); - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 0); - - try { stmt.execute(); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 4); - } - count = 0; - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 4); -} - - -void SQLExecutor::insertEmptyDeque() -{ - std::string funct = "insertEmptyDeque()"; - std::deque str; - - try - { - session() << "INSERT INTO Strings VALUES (?)", use(str), now; - fail("empty collections should not work"); - } - catch (Poco::Exception&) - { - } -} - - -void SQLExecutor::affectedRows(const std::string& whereClause) -{ - std::vector str; - str.push_back("s1"); - str.push_back("s2"); - str.push_back("s3"); - str.push_back("s3"); - int count = 100; - - Statement stmt1((session() << "INSERT INTO Strings VALUES(?)", use(str))); - session() << "SELECT COUNT(*) FROM Strings", into(count), now; - assertTrue (count == 0); - assertTrue (4 == stmt1.execute()); - session() << "SELECT COUNT(*) FROM Strings", into(count), now; - assertTrue (count == 4); - - Statement stmt2(session() << "UPDATE Strings SET str = 's4' WHERE str = 's3'"); - assertTrue (2 == stmt2.execute()); - - Statement stmt3(session() << "DELETE FROM Strings WHERE str = 's1'"); - assertTrue (1 == stmt3.execute()); - - std::string sql; - format(sql, "DELETE FROM Strings %s", whereClause); - Statement stmt4(session() << sql); - assertTrue (3 == stmt4.execute()); -} - - -void SQLExecutor::insertSingleBulk() -{ - std::string funct = "insertSingleBulk()"; - int x = 0; - Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(x))); - - for (x = 0; x < 100; ++x) - { - std::size_t i = stmt.execute(); - assertTrue (1 == i); - } - int count = 0; - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 100); - - try { session() << "SELECT SUM(str) FROM Strings", 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); } - assertTrue (count == ((0+99)*100/2)); -} - - -void SQLExecutor::floats() -{ - std::string funct = "floats()"; - float data = 1.5f; - float ret = 0.0f; - - try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 1); - - try { session() << "SELECT str FROM Strings", into(ret), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (ret == data); -} - - -void SQLExecutor::doubles() -{ - std::string funct = "floats()"; - double data = 1.5; - double ret = 0.0; - - try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 1); - - try { session() << "SELECT str FROM Strings", into(ret), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (ret == data); -} - - -void SQLExecutor::uuids() -{ - std::string funct = "uuids()"; - Poco::UUID data("49cf6461-9b62-4163-9659-5472ef73153d"); - Poco::UUID ret; - - try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 1); - - try { session() << "SELECT str FROM Strings", into(ret), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (ret == data); -} - - -void SQLExecutor::insertSingleBulkVec() -{ - std::string funct = "insertSingleBulkVec()"; - std::vector data; - - for (int x = 0; x < 100; ++x) - data.push_back(x); - - Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(data))); - stmt.execute(); - - int count = 0; - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - - assertTrue (count == 100); - try { session() << "SELECT SUM(str) FROM Strings", 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); } - assertTrue (count == ((0+99)*100/2)); -} - - -void SQLExecutor::limits() -{ - std::string funct = "limit()"; - std::vector data; - for (int x = 0; x < 100; ++x) - { - data.push_back(x); - } - - try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - std::vector retData; - try { session() << "SELECT * FROM Strings", into(retData), limit(50), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (retData.size() == 50); - for (int x = 0; x < 50; ++x) - { - assertTrue (data[x] == retData[x]); - } -} - - -void SQLExecutor::limitZero() -{ - std::string funct = "limitZero()"; - std::vector data; - for (int x = 0; x < 100; ++x) - { - data.push_back(x); - } - - try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - std::vector retData; - try { session() << "SELECT * FROM Strings", into(retData), limit(0), now; }// stupid test, but at least we shouldn't crash - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (retData.size() == 0); -} - - -void SQLExecutor::limitOnce() -{ - std::string funct = "limitOnce()"; - std::vector data; - for (int x = 0; x < 101; ++x) - { - data.push_back(x); - } - - try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - std::vector retData; - Statement stmt = (session() << "SELECT * FROM Strings", into(retData), limit(50), now); - assertTrue (!stmt.done()); - assertTrue (retData.size() == 50); - stmt.execute(); - assertTrue (!stmt.done()); - assertTrue (retData.size() == 100); - stmt.execute(); - assertTrue (stmt.done()); - assertTrue (retData.size() == 101); - - for (int x = 0; x < 101; ++x) - { - assertTrue (data[x] == retData[x]); - } -} - - -void SQLExecutor::limitPrepare() -{ - std::string funct = "limitPrepare()"; - std::vector data; - for (int x = 0; x < 100; ++x) - { - data.push_back(x); - } - - try - { - Statement stmt = (session() << "INSERT INTO Strings VALUES (?)", use(data)); - assertTrue (100 == stmt.execute()); - } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - std::vector retData; - Statement stmt = (session() << "SELECT * FROM Strings", into(retData), limit(50)); - assertTrue (retData.size() == 0); - assertTrue (!stmt.done()); - - try { stmt.execute(); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (!stmt.done()); - assertTrue (retData.size() == 50); - - try { stmt.execute(); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (stmt.done()); - assertTrue (retData.size() == 100); - - try { stmt.execute(); }// will restart execution! - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - assertTrue (!stmt.done()); - assertTrue (retData.size() == 150); - for (int x = 0; x < 150; ++x) - { - assertTrue (data[x%100] == retData[x]); - } -} - - -void SQLExecutor::prepare() -{ - std::string funct = "prepare()"; - std::vector data; - for (int x = 0; x < 100; x += 2) - { - data.push_back(x); - } - - { - Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(data))); - } - - // stmt should not have been executed when destroyed - int count = 100; - try { session() << "SELECT COUNT(*) FROM Strings", 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); } - assertTrue (count == 0); -} - - -void SQLExecutor::doBulkPerformance(Poco::UInt32 size) -{ - std::string funct = "doBulk()"; - std::vector ints(size, 1); - std::vector strings(size, "abc"); - std::vector floats(size, .5); - std::vector dateTimes(size); - - Stopwatch sw; - try - { - sw.start(); - session() << "INSERT INTO MiscTest (First, Third, Fourth, Fifth) VALUES (?,?,?,?)", - use(strings), - use(ints), - use(floats), - use(dateTimes), now; - sw.stop(); - } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - double time = sw.elapsed() / 1000.0; - - try { session() << "DELETE FROM MiscTest", now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try - { - sw.restart(); - session() << "INSERT INTO MiscTest (First, Third, Fourth, Fifth) VALUES (?,?,?,?)", - use(strings, bulk), - use(ints, bulk), - use(floats, bulk), - use(dateTimes, bulk), now; - sw.stop(); - } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - double bulkTime = sw.elapsed() / 1000.0; - - double speedup; - if (0.0 == bulkTime) - { - if (0.0 == time) speedup = 1.0; - else speedup = time; - } - else - speedup = time / bulkTime; - - std::cout << "INSERT => Size:" << size - << ", Time: " << time - << ", Bulk Time: " << bulkTime - << " [ms], Speedup: " << speedup - << 'x' << std::endl; - - ints.clear(); - strings.clear(); - floats.clear(); - dateTimes.clear(); - - try - { - sw.restart(); - session() << "SELECT First, Third, Fourth, Fifth FROM MiscTest", - into(strings), - into(ints), - into(floats), - into(dateTimes), - now; - sw.stop(); - } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - time = sw.elapsed() / 1000.0; - - assertTrue (ints.size() == size); - - ints.clear(); - strings.clear(); - floats.clear(); - dateTimes.clear(); - - try - { - sw.restart(); - session() << "SELECT First, Third, Fourth, Fifth FROM MiscTest", - into(strings, bulk(size)), - into(ints, bulk(size)), - into(floats, bulk(size)), - into(dateTimes, bulk(size)), - now; - sw.stop(); - } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - bulkTime = sw.elapsed() / 1000.0; - - assertTrue (ints.size() == size); - - if (0.0 == bulkTime) - { - if (0.0 == time) speedup = 1.0; - else speedup = time; - } - else - speedup = time / bulkTime; - - std::cout << "SELECT => Size:" << size - << ", Time: " << time - << ", Bulk Time: " << bulkTime - << " [ms], Speedup: " << speedup - << 'x' << std::endl; -} - - -void SQLExecutor::setSimple() -{ - std::string funct = "setSimple()"; - std::set lastNames; - std::set firstNames; - std::set addresses; - std::set ages; - std::string tableName("Person"); - lastNames.insert("LN1"); - lastNames.insert("LN2"); - firstNames.insert("FN1"); - firstNames.insert("FN2"); - addresses.insert("ADDR1"); - addresses.insert("ADDR2"); - ages.insert(1); - ages.insert(2); - int count = 0; - std::string result; - - 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); } - 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); } - assertTrue (count == 2); - - std::set lastNamesR; - std::set firstNamesR; - std::set addressesR; - std::set agesR; - try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (ages == agesR); - assertTrue (lastNames == lastNamesR); - assertTrue (firstNames == firstNamesR); - assertTrue (addresses == addressesR); -} - - -void SQLExecutor::setComplex() -{ - std::string funct = "setComplex()"; - std::set people; - people.insert(Person("LN1", "FN1", "ADDR1", 1)); - people.insert(Person("LN2", "FN2", "ADDR2", 2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 2); - - std::set result; - try { session() << "SELECT * FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result == people); -} - - -void SQLExecutor::setComplexUnique() -{ - std::string funct = "setComplexUnique()"; - std::vector people; - Person p1("LN1", "FN1", "ADDR1", 1); - people.push_back(p1); - people.push_back(p1); - people.push_back(p1); - people.push_back(p1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.push_back(p2); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 5); - - std::set result; - try { session() << "SELECT * FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result.size() == 2); - assertTrue (*result.begin() == p1); - assertTrue (*++result.begin() == p2); -} - -void SQLExecutor::multiSetSimple() -{ - std::string funct = "multiSetSimple()"; - std::multiset lastNames; - std::multiset firstNames; - std::multiset addresses; - std::multiset ages; - std::string tableName("Person"); - lastNames.insert("LN1"); - lastNames.insert("LN2"); - firstNames.insert("FN1"); - firstNames.insert("FN2"); - addresses.insert("ADDR1"); - addresses.insert("ADDR2"); - ages.insert(1); - ages.insert(2); - int count = 0; - std::string result; - - 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); } - 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); } - assertTrue (count == 2); - - std::multiset lastNamesR; - std::multiset firstNamesR; - std::multiset addressesR; - std::multiset agesR; - try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (ages.size() == agesR.size()); - assertTrue (lastNames.size() == lastNamesR.size()); - assertTrue (firstNames.size() == firstNamesR.size()); - assertTrue (addresses.size() == addressesR.size()); -} - - -void SQLExecutor::multiSetComplex() -{ - std::string funct = "multiSetComplex()"; - std::multiset people; - Person p1("LN1", "FN1", "ADDR1", 1); - people.insert(p1); - people.insert(p1); - people.insert(p1); - people.insert(p1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(p2); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 5); - - std::multiset result; - try { session() << "SELECT * FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result.size() == people.size()); -} - - -void SQLExecutor::mapComplex() -{ - std::string funct = "mapComplex()"; - std::map people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN2", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 2); - - std::map result; - try { session() << "SELECT * FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result == people); -} - - -void SQLExecutor::mapComplexUnique() -{ - std::string funct = "mapComplexUnique()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN2", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 5); - - std::map result; - try { session() << "SELECT * FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result.size() == 2); -} - - -void SQLExecutor::multiMapComplex() -{ - std::string funct = "multiMapComplex()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN2", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 5); - - std::multimap result; - try { session() << "SELECT * FROM Person", into(result), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result.size() == people.size()); -} - - -void SQLExecutor::selectIntoSingle() -{ - std::string funct = "selectIntoSingle()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN2", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 2); - Person result; - try { session() << "SELECT * FROM Person ORDER BY LastName", into(result), limit(1), now; }// will return 1 object into one single result - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result == p1); -} - - -void SQLExecutor::selectIntoSingleStep() -{ - std::string funct = "selectIntoSingleStep()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN2", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - 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); } - assertTrue (count == 2); - Person result; - Statement stmt = (session() << "SELECT * FROM Person", into(result), limit(1)); - stmt.execute(); - assertTrue (result == p1); - assertTrue (!stmt.done()); - stmt.execute(); - assertTrue (result == p2); - assertTrue (stmt.done()); -} - - -void SQLExecutor::selectIntoSingleFail() -{ - std::string funct = "selectIntoSingleFail()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN2", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - try { session() << "SELECT COUNT(*) FROM Person", into(count), limit(2, true), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (count == 2); - Person result; - try - { - session() << "SELECT * FROM Person", into(result), limit(1, true), now; // will fail now - fail("hardLimit is set: must fail"); - } - catch(Poco::Data::LimitException&) - { - } -} - - -void SQLExecutor::lowerLimitOk() -{ - std::string funct = "lowerLimitOk()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - 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); } - assertTrue (count == 2); - Person result; - try - { - session() << "SELECT * FROM Person", into(result), lowerLimit(2), now; // will return 2 objects into one single result but only room for one! - fail("Not enough space for results"); - } - catch(Poco::Exception&) - { - } -} - - -void SQLExecutor::singleSelect() -{ - std::string funct = "singleSelect()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - 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); } - assertTrue (count == 2); - Person result; - Statement stmt = (session() << "SELECT * FROM Person", into(result), limit(1)); - stmt.execute(); - assertTrue (result == p1); - assertTrue (!stmt.done()); - stmt.execute(); - assertTrue (result == p2); - assertTrue (stmt.done()); -} - - -void SQLExecutor::lowerLimitFail() -{ - std::string funct = "lowerLimitFail()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 2); - Person result; - try - { - session() << "SELECT * FROM Person", into(result), lowerLimit(3), now; // will fail - fail("should fail. not enough data"); - } - catch(Poco::Exception&) - { - } -} - - -void SQLExecutor::combinedLimits() -{ - std::string funct = "combinedLimits()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 2); - std::vector result; - try { session() << "SELECT * FROM Person", into(result), lowerLimit(2), upperLimit(2), now; }// will return 2 objects - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result.size() == 2); - assertTrue (result[0] == p1); - assertTrue (result[1] == p2); -} - - - -void SQLExecutor::ranges() -{ - std::string funct = "range()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 2); - std::vector result; - try { session() << "SELECT * FROM Person", into(result), range(2, 2), now; }// will return 2 objects - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (result.size() == 2); - assertTrue (result[0] == p1); - assertTrue (result[1] == p2); -} - - -void SQLExecutor::combinedIllegalLimits() -{ - std::string funct = "combinedIllegalLimits()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 2); - Person result; - try - { - session() << "SELECT * FROM Person", into(result), lowerLimit(3), upperLimit(2), now; - fail("lower > upper is not allowed"); - } - catch(LimitException&) - { - } -} - - -void SQLExecutor::illegalRange() -{ - std::string funct = "illegalRange()"; - std::multimap people; - Person p1("LN1", "FN1", "ADDR1", 1); - Person p2("LN2", "FN2", "ADDR2", 2); - people.insert(std::make_pair("LN1", p1)); - people.insert(std::make_pair("LN1", p2)); - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - int count = 0; - 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); } - assertTrue (count == 2); - Person result; - try - { - session() << "SELECT * FROM Person", into(result), range(3, 2), now; - fail("lower > upper is not allowed"); - } - catch(LimitException&) - { - } -} - - -void SQLExecutor::emptyDB() -{ - std::string funct = "emptyDB()"; - int count = 0; - 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); } - assertTrue (count == 0); - - Person result; - Statement stmt = (session() << "SELECT * FROM Person", into(result), limit(1)); - stmt.execute(); - assertTrue (result.firstName.empty()); - assertTrue (stmt.done()); -} - - -void SQLExecutor::blob(int bigSize, const std::string& blobPlaceholder) -{ - std::string funct = "blob()"; - std::string lastName("lastname"); - std::string firstName("firstname"); - std::string address("Address"); - - CLOB img("0123456789", 10); - int count = 0; - try { session() << format("INSERT INTO Person VALUES (?,?,?,%s)", blobPlaceholder), - use(lastName), use(firstName), use(address), use(img), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - 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); } - assertTrue (count == 1); - - CLOB res; - assertTrue (res.size() == 0); - try { session() << "SELECT Image FROM Person", into(res), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (res == img); - - CLOB big; - std::vector v(bigSize, 'x'); - big.assignRaw(&v[0], v.size()); - - assertTrue (big.size() == bigSize); - - try { session() << "DELETE FROM Person", now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try { session() << format("INSERT INTO Person VALUES (?,?,?,%s)", blobPlaceholder), - use(lastName), use(firstName), use(address), use(big), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try { session() << "SELECT Image FROM Person", into(res), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (res == big); -} - - -void SQLExecutor::blobStmt() -{ - std::string funct = "blobStmt()"; - std::string lastName("lastname"); - std::string firstName("firstname"); - std::string address("Address"); - CLOB blob("0123456789", 10); - - int count = 0; - Statement ins = (session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(blob)); - ins.execute(); - 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); } - assertTrue (count == 1); - - CLOB res; - poco_assert (res.size() == 0); - Statement stmt = (session() << "SELECT Image FROM Person", into(res)); - try { stmt.execute(); } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - poco_assert (res == blob); -} - - -void SQLExecutor::recordSet() -{ - std::string funct = "dateTime()"; - - std::string lastName("lastname"); - std::string firstName("firstname"); - std::string address("Address"); - DateTime born(1965, 6, 18, 5, 35, 1); - DateTime born2(1991, 6, 18, 14, 35, 1); - - try - { - { - Statement stmt = (session() << "SELECT COUNT(*) AS row_count FROM Person", now); - RecordSet rset(stmt); - assertTrue (rset.rowCount() == 1); - assertTrue (rset["row_count"].convert() == 0); - } - - { - Statement stmt = (session() << - "INSERT INTO Person VALUES (?,?,?,?)", - use(lastName), use(firstName), use(address), use(born), now); - RecordSet rset(stmt); - assertTrue (rset.rowCount() == 0); - assertTrue (rset.affectedRowCount() == 1); - } - - { - Statement stmt = (session() << "SELECT COUNT(*) AS row_count FROM Person", now); - RecordSet rset(stmt); - assertTrue (rset.rowCount() == 1); - assertTrue (rset["row_count"].convert() == 1); - } - - { - Statement stmt = (session() << "SELECT Born FROM Person", now); - RecordSet rset(stmt); - assertTrue (rset.rowCount() == 1); - assertTrue (rset["Born"].convert() == born); - } - - { - Statement stmt = (session() << - "DELETE FROM Person WHERE born = ?", use(born), now); - RecordSet rset(stmt); - assertTrue (rset.rowCount() == 0); - assertTrue (rset.affectedRowCount() == 1); - } - - { - Statement stmt = (session() << - "INSERT INTO Person VALUES (?,?,?,?)", - use(lastName), use(firstName), use(address), use(born), now); - RecordSet rset(stmt); - assertTrue (rset.rowCount() == 0); - assertTrue (rset.affectedRowCount() == 1); - } - - { - Statement stmt = (session() << - "INSERT INTO Person VALUES (?,?,?,?)", - use(lastName), use(firstName), use(address), use(born2), now); - RecordSet rset(stmt); - assertTrue (rset.rowCount() == 0); - assertTrue (rset.affectedRowCount() == 1); - } - - { - Statement stmt = (session() << "SELECT COUNT(*) AS row_count FROM Person", now); - RecordSet rset(stmt); - assertTrue (rset.rowCount() == 1); - assertTrue (rset["row_count"].convert() == 2); - } - - { - Statement stmt = (session() << "SELECT Born FROM Person ORDER BY Born DESC", now); - RecordSet rset(stmt); - assertTrue (rset.rowCount() == 2); - assertTrue (rset["Born"].convert() == born2); - rset.moveNext(); - assertTrue (rset["Born"].convert() == born); - rset.moveFirst(); - assertTrue (rset["Born"].convert() == born2); - rset.moveLast(); - assertTrue (rset["Born"].convert() == born); - } - - { - Statement stmt = (session() << "DELETE FROM Person", now); - RecordSet rset(stmt); - assertTrue (rset.rowCount() == 0); - assertTrue (rset.affectedRowCount() == 2); - } - } - catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); } - catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); } -} - - -void SQLExecutor::dateTime() -{ - std::string funct = "dateTime()"; - std::string lastName("lastname"); - std::string firstName("firstname"); - std::string address("Address"); - - DateTime born(1965, 6, 18, 5, 35, 1); - int count = 0; - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(born), now; } - catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); } - catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); } - 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); } - assertTrue (count == 1); - - DateTime res; - try { session() << "SELECT Born FROM Person", into(res), now; } - catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); } - catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); } - assertTrue (res == born); - - Statement stmt = (session() << "SELECT Born FROM Person", now); - RecordSet rset(stmt); - - res = rset["Born"].convert(); - assertTrue (res == born); -} - - -void SQLExecutor::date() -{ - std::string funct = "date()"; - std::string lastName("lastname"); - std::string firstName("firstname"); - std::string address("Address"); - - Date bornDate(1965, 6, 18); - int count = 0; - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", - use(lastName), - use(firstName), - use(address), - use(bornDate), - now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - 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); } - assertTrue (count == 1); - - Date d; - Time t; - try { session() << "SELECT BornDate FROM Person", into(d), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (d == bornDate); - - Statement stmt = (session() << "SELECT BornDate FROM Person", now); - RecordSet rset(stmt); - - DateTime dt1 = rset["BornDate"].convert(); - - Date d2(dt1); - assertTrue (d2 == bornDate); -} - - -void SQLExecutor::time() -{ - std::string funct = "time()"; - std::string lastName("lastname"); - std::string firstName("firstname"); - std::string address("Address"); - - Time bornTime (5, 35, 1); - int count = 0; - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", - use(lastName), - use(firstName), - use(address), - use(bornTime), - now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - 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); } - assertTrue (count == 1); - - Date d; - Time t; - try { session() << "SELECT BornTime FROM Person", into(t), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (t == bornTime); - - Statement stmt = (session() << "SELECT BornTime FROM Person", now); - RecordSet rset(stmt); - - DateTime dt2 = rset["BornTime"].convert(); - Time t2(dt2); - assertTrue (t2 == bornTime); -} - - -void SQLExecutor::tuples() -{ - typedef Tuple TupleType; - std::string funct = "tuples()"; - TupleType t(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19); - - try { session() << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", use(t), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - TupleType ret(-10,-11,-12,-13,-14,-15,-16,-17,-18,-19); - assertTrue (ret != t); - try { session() << "SELECT * FROM Tuples", into(ret), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (ret == t); -} - -void SQLExecutor::tupleVector() -{ - typedef Tuple TupleType; - std::string funct = "tupleVector()"; - TupleType t(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19); - Tuple - t10(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29); - TupleType t100(100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119); - std::vector v; - v.push_back(t); - v.push_back(t10); - v.push_back(t100); - - try { session() << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", use(v), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int count = 0; - try { session() << "SELECT COUNT(*) FROM Tuples", 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); } - assertTrue (v.size() == count); - - std::vector > ret; - try { session() << "SELECT * FROM Tuples", into(ret), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - assertTrue (ret == v); -} - - -void SQLExecutor::internalExtraction() -{ - std::string funct = "internalExtraction()"; - std::vector > v; - v.push_back(Tuple(1, 1.5f, "3")); - v.push_back(Tuple(2, 2.5f, "4")); - v.push_back(Tuple(3, 3.5f, "5")); - v.push_back(Tuple(4, 4.5f, "6")); - - try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try - { - Statement stmt = (session() << "SELECT * FROM Vectors", now); - RecordSet rset(stmt); - - assertTrue (3 == rset.columnCount()); - assertTrue (4 == rset.rowCount()); - - int curVal = 3; - do - { - assertTrue (rset["str0"] == curVal); - ++curVal; - } while (rset.moveNext()); - - rset.moveFirst(); - assertTrue (rset["str0"] == "3"); - rset.moveLast(); - assertTrue (rset["str0"] == "6"); - - RecordSet rset2(rset); - assertTrue (3 == rset2.columnCount()); - assertTrue (4 == rset2.rowCount()); - - int i = rset.value(0,0); - assertTrue (1 == i); - - std::string s = rset.value(0,0).convert(); - assertTrue ("1" == s); - - int a = rset.value(0,2); - assertTrue (3 == a); - - try - { - double d = rset.value(1,1); - assertTrue (2.5 == d); - } - catch (BadCastException&) - { - float f = rset.value(1,1); - assertTrue (2.5 == f); - } - - try - { - s = rset.value(2, 2); - } - catch (BadCastException&) - { - UTF16String us = rset.value(2, 2); - Poco::UnicodeConverter::convert(us, s); - } - assertTrue ("5" == s); - - i = rset.value("str0", 2); - assertTrue (5 == i); - - const Column >& col = rset.column >(0); - Column >::Iterator it = col.begin(); - Column >::Iterator end = col.end(); - for (int i = 1; it != end; ++it, ++i) - assertTrue (*it == i); - - rset = (session() << "SELECT COUNT(*) AS cnt FROM Vectors", now); - - //various results for COUNT(*) are received from different drivers - try - { - //this is what most drivers will return - int i = rset.value(0,0); - assertTrue (4 == i); - } - catch(BadCastException&) - { - try - { - //this is for Oracle - double i = rset.value(0,0); - assertTrue (4 == int(i)); - } - catch(BadCastException&) - { - //this is for PostgreSQL - Poco::Int64 big = rset.value(0,0); - assertTrue (4 == big); - } - } - - s = rset.value("cnt", 0).convert(); - assertTrue ("4" == s); - - try { rset.column >(100); fail ("must fail"); } - catch (RangeException&) { } - - try { rset.value(0,0); fail ("must fail"); } - catch (BadCastException&) { } - - stmt = (session() << "DELETE FROM Vectors", now); - rset = stmt; - - try { rset.column >(0); fail ("must fail"); } - catch (RangeException&) { } - } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } -} - - -void SQLExecutor::filter(const std::string& query, const std::string& intFldName) -{ - std::string funct = "filter()"; - std::vector > v; - v.push_back(Tuple(1, 1.5f, "3")); - v.push_back(Tuple(2, 2.5f, "4")); - v.push_back(Tuple(3, 3.5f, "5")); - v.push_back(Tuple(4, 4.5f, "6")); - - try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try - { - Statement stmt = (session() << query, now); - RecordSet rset(stmt); - assertTrue (rset.totalRowCount() == 4); - RowFilter::Ptr pRF = new RowFilter(&rset); - assertTrue (pRF->isEmpty()); - pRF->add(intFldName, RowFilter::VALUE_EQUAL, 1); - assertTrue (!pRF->isEmpty()); - - Var da; - try - { - da = rset.value(0, 1); - fail ("must fail"); - } catch (InvalidAccessException&) - { - da = rset.value(0, 1, false); - assertTrue (2 == da); - da = rset.value(0, 0); - assertTrue (1 == da); - } - - assertTrue (rset.rowCount() == 1); - assertTrue (rset.moveFirst()); - assertTrue (1 == rset[intFldName]); - assertTrue (!rset.moveNext()); - pRF->add("flt0", RowFilter::VALUE_LESS_THAN_OR_EQUAL, 3.5f); - assertTrue (rset.rowCount() == 3); - assertTrue (rset.moveNext()); - assertTrue (2.5 == rset["flt0"]); - assertTrue (rset.moveNext()); - assertTrue (3.5 == rset["flt0"]); - assertTrue (!rset.moveNext()); - pRF->add("str0", RowFilter::VALUE_EQUAL, 6); - assertTrue (rset.rowCount() == 4); - assertTrue (rset.moveLast()); - assertTrue ("6" == rset["str0"]); - pRF->remove("flt0"); - assertTrue (rset.rowCount() == 2); - assertTrue (rset.moveFirst()); - assertTrue ("3" == rset["str0"]); - assertTrue (rset.moveNext()); - assertTrue ("6" == rset["str0"]); - pRF->remove(intFldName); - pRF->remove("str0"); - assertTrue (pRF->isEmpty()); - pRF->add("str0", "!=", 3); - assertTrue (rset.rowCount() == 3); - - RowFilter::Ptr pRF1 = new RowFilter(pRF, RowFilter::OP_AND); - pRF1->add(intFldName, "==", 2); - assertTrue (rset.rowCount() == 1); - pRF1->add(intFldName, "<", 2); - assertTrue (rset.rowCount() == 1); - pRF1->add(intFldName, ">", 3); - assertTrue (rset.rowCount() == 2); - pRF->removeFilter(pRF1); - pRF->remove("str0"); - assertTrue (pRF->isEmpty()); - assertTrue (rset.rowCount() == 4); - } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } -} - - -void SQLExecutor::internalBulkExtraction() -{ - std::string funct = "internalBulkExtraction()"; - int size = 100; - std::vector lastName(size); - std::vector firstName(size); - std::vector address(size); - std::vector age(size); - - for (int i = 0; i < size; ++i) - { - lastName[i] = "LN" + NumberFormatter::format(i); - firstName[i] = "FN" + NumberFormatter::format(i); - address[i] = "Addr" + NumberFormatter::format(i); - age[i] = i; - } - - try - { - session() << "INSERT INTO Person VALUES (?,?,?,?)", - use(lastName, bulk), - use(firstName, bulk), - use(address, bulk), - use(age, bulk), - now; - } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try - { - Statement stmt = (session() << "SELECT * FROM Person", bulk(size), now); - RecordSet rset(stmt); - assertTrue (size == rset.rowCount()); - assertTrue ("LN0" == rset["LastName"]); - assertTrue (0 == rset["Age"]); - rset.moveNext(); - assertTrue ("LN1" == rset["LastName"]); - assertTrue (1 == rset["Age"]); - rset.moveLast(); - assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]); - assertTrue (size - 1 == rset["Age"]); - } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try - { - Statement stmt = (session() << "SELECT * FROM Person", limit(size), bulk, now); - RecordSet rset(stmt); - assertTrue (size == rset.rowCount()); - assertTrue ("LN0" == rset["LastName"]); - assertTrue (0 == rset["Age"]); - rset.moveLast(); - assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]); - assertTrue (size - 1 == rset["Age"]); - } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } -} - - -void SQLExecutor::internalBulkExtractionUTF16() -{ - std::string funct = "internalBulkExtraction()"; - int size = 100; - std::vector lastName(size); - std::vector firstName(size); - std::vector address(size); - std::vector age(size); - - for (int i = 0; i < size; ++i) - { - lastName[i] = Poco::UnicodeConverter::to("LN" + NumberFormatter::format(i)); - firstName[i] = Poco::UnicodeConverter::to("FN" + NumberFormatter::format(i)); - address[i] = Poco::UnicodeConverter::to("Addr" + NumberFormatter::format(i)); - age[i] = i; - } - - try - { - session() << "INSERT INTO Person VALUES (?,?,?,?)", - use(lastName, bulk), - use(firstName, bulk), - use(address, bulk), - use(age, bulk), - now; - } - catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); } - catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); } - - try - { - Statement stmt = (session() << "SELECT * FROM Person", bulk(size), now); - RecordSet rset(stmt); - assertTrue (size == rset.rowCount()); - assertTrue (Poco::UnicodeConverter::to("LN0") == rset["LastName"]); - assertTrue (0 == rset["Age"]); - rset.moveNext(); - assertTrue (Poco::UnicodeConverter::to("LN1") == rset["LastName"]); - assertTrue (1 == rset["Age"]); - rset.moveLast(); - assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]); - assertTrue (size - 1 == rset["Age"]); - } - catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); } - catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); } - - try - { - Statement stmt = (session() << "SELECT * FROM Person", limit(size), bulk, now); - RecordSet rset(stmt); - assertTrue (size == rset.rowCount()); - assertTrue ("LN0" == rset["LastName"]); - assertTrue (0 == rset["Age"]); - rset.moveLast(); - assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]); - assertTrue (size - 1 == rset["Age"]); - } - catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); } - catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); } -} - - -void SQLExecutor::internalStorageType() -{ - std::string funct = "internalStorageType()"; - std::vector manips; - manips.push_back(list); - manips.push_back(deque); - manips.push_back(vector); - - std::vector > v; - v.push_back(Tuple(1, 1.5f, "3")); - v.push_back(Tuple(2, 2.5f, "4")); - v.push_back(Tuple(3, 3.5f, "5")); - v.push_back(Tuple(4, 4.5f, "6")); - - try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try - { - std::vector::iterator it = manips.begin(); - std::vector::iterator end = manips.end(); - - for (; it != end; ++it) - { - Statement stmt = (session() << "SELECT * FROM Vectors", *it, now); - RecordSet rset(stmt); - - assertTrue (3 == rset.columnCount()); - assertTrue (4 == rset.rowCount()); - - int curVal = 3; - do - { - assertTrue (rset["str0"] == curVal); - ++curVal; - } while (rset.moveNext()); - - rset.moveFirst(); - assertTrue (rset["str0"] == "3"); - rset.moveLast(); - assertTrue (rset["str0"] == "6"); - - try - { - stmt = (session() << "SELECT * FROM Vectors", now, *it); - fail ("must fail"); - } - catch(InvalidAccessException&){} - - try - { - stmt = (session() << "SELECT * FROM Vectors", into(v), now, *it); - fail ("must fail"); - } - catch(InvalidAccessException&){} - - try - { - stmt = (session() << "SELECT * FROM Vectors", into(v), *it, now); - fail ("must fail"); - } - catch(InvalidAccessException&){} - } - } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } -} - - void SQLExecutor::notNulls(const std::string& sqlState) { try { session() << "INSERT INTO NullTest (i,r,v) VALUES (?,?,?)", use(null), use(null), use(null), now; fail ("must fail"); - }catch (StatementException& se) + } catch (StatementException& se) { //double check if we're failing for the right reason //default sqlState value is "23502"; some drivers report "HY???" codes @@ -3616,318 +1046,6 @@ void SQLExecutor::notNulls(const std::string& sqlState) } -void SQLExecutor::nulls() -{ - std::string funct = "nulls()"; - - try { session() << "INSERT INTO NullTest (i,r,v) VALUES (?,?,?)", use(null), use(null), use(null), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - RecordSet rs(session(), "SELECT * FROM NullTest"); - assertTrue (1 == rs.rowCount()); - rs.moveFirst(); - assertTrue (rs.isNull("i")); - assertTrue (rs["i"] != 0); - assertTrue (rs.isNull("r")); - assertTrue (rs.isNull("v")); - assertTrue (rs["v"] != ""); - assertTrue (rs.nvl("i") == 0); - assertTrue (rs.nvl("i", -1) == -1); - assertTrue (rs.nvl("r") == double()); - assertTrue (rs.nvl("r", -1.5) == -1.5); - assertTrue (rs.nvl("v") == ""); - assertTrue (rs.nvl("v", "123") == "123"); - try { session() << "DELETE FROM NullTest", now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - int i = 1; - double f = 1.5; - std::string s = "123"; - - try { session() << "INSERT INTO NullTest (i, r, v) VALUES (?,?,?)", use(i), use(f), use(s), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - rs = (session() << "SELECT * FROM NullTest", now); - assertTrue (1 == rs.rowCount()); - rs.moveFirst(); - assertTrue (!rs.isNull("i")); - assertTrue (rs["i"] == 1); - assertTrue (!rs.isNull("v")); - assertTrue (!rs.isNull("r")); - assertTrue (rs["v"] == "123"); - assertTrue (rs.nvl("i") == 1); - assertTrue (rs.nvl("i", -1) == 1); - assertTrue (rs.nvl("r") == 1.5); - assertTrue (rs.nvl("r", -1.5) == 1.5); - assertTrue (rs.nvl("v") == "123"); - assertTrue (rs.nvl("v", "456") == "123"); - try { session() << "UPDATE NullTest SET v = ? WHERE i = ?", use(null), use(i), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - i = 2; - f = 3.4; - try { session() << "INSERT INTO NullTest (i, r, v) VALUES (?,?,?)", use(i), use(null), use(null), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - rs = (session() << "SELECT i, r, v FROM NullTest ORDER BY i ASC", now); - assertTrue (2 == rs.rowCount()); - rs.moveFirst(); - assertTrue (!rs.isNull("i")); - assertTrue (rs["i"] == 1); - assertTrue (!rs.isNull("r")); - assertTrue (rs.isNull("v")); - assertTrue (rs["v"] != ""); - - assertTrue (rs.moveNext()); - assertTrue (!rs.isNull("i")); - assertTrue (rs["i"] == 2); - assertTrue (rs.isNull("r")); - assertTrue (rs.isNull("v")); - assertTrue (rs["v"] != ""); - - try { session() << "DELETE FROM NullTest", now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - try { session() << "INSERT INTO NullTest (v) VALUES (?)", bind(""), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - bool esin = session().getFeature("emptyStringIsNull"); - session().setFeature("emptyStringIsNull", true); - - try - { - session().setFeature("forceEmptyString", true); - fail ("must fail"); - } catch (InvalidAccessException&) { } - - bool fes = session().getFeature("forceEmptyString"); - session().setFeature("forceEmptyString", false); - - RecordSet rs1(session(), "SELECT v FROM NullTest"); - assertTrue (1 == rs1.rowCount()); - rs1.moveFirst(); - assertTrue (rs1.isNull("v")); - assertTrue (!(rs["v"] == "")); - - session().setFeature("emptyStringIsNull", false); - session().setFeature("forceEmptyString", true); - RecordSet rs2(session(), "SELECT v FROM NullTest"); - assertTrue (1 == rs2.rowCount()); - rs2.moveFirst(); - assertTrue (!rs2.isNull("v")); - assertTrue ((rs2["v"] == "")); - - try - { - session().setFeature("emptyStringIsNull", true); - fail ("must fail"); - } catch (InvalidAccessException&) { } - - session().setFeature("emptyStringIsNull", esin); - session().setFeature("forceEmptyString", fes); -} - - -void SQLExecutor::rowIterator() -{ - std::string funct = "rowIterator()"; - std::vector > v; - v.push_back(Tuple(1, 1.5f, "3")); - v.push_back(Tuple(2, 2.5f, "4")); - v.push_back(Tuple(3, 3.5f, "5")); - v.push_back(Tuple(4, 4.5f, "6")); - - try { session() << "DELETE FROM Vectors", now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - RecordSet rset0(session(), "SELECT * FROM Vectors"); - assertTrue (rset0.begin() == rset0.end()); - - try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - RecordSet rset(session(), "SELECT * FROM Vectors"); - - std::ostringstream osLoop; - RecordSet::Iterator it = rset.begin(); - RecordSet::Iterator end = rset.end(); - for (int i = 1; it != end; ++it, ++i) - { - assertTrue (it->get(0) == i); - osLoop << *it; - } - assertTrue (!osLoop.str().empty()); - - std::ostringstream osCopy; - std::copy(rset.begin(), rset.end(), std::ostream_iterator(osCopy)); - assertTrue (osLoop.str() == osCopy.str()); - - RowFilter::Ptr pRF = new RowFilter(&rset); - assertTrue (pRF->isEmpty()); - pRF->add("str0", RowFilter::VALUE_EQUAL, "3"); - assertTrue (!pRF->isEmpty()); - it = rset.begin(); - end = rset.end(); - for (int i = 1; it != end; ++it, ++i) - { - assertTrue (it->get(0) == i); - assertTrue (1 == i); - } -} - - -void SQLExecutor::stdVectorBool() -{ - std::string funct = "stdVectorBool()"; - - bool b = false; - try { session() << "INSERT INTO BoolTest VALUES (?)", use(b), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - b = true; - session() << "SELECT * FROM BoolTest", into(b), now; - assertTrue (false == b); - session() << "DELETE FROM BoolTest", now; - - b = true; - try { session() << "INSERT INTO BoolTest VALUES (?)", use(b), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - b = false; - session() << "SELECT * FROM BoolTest", into(b), now; - assertTrue (true == b); - session() << "DELETE FROM BoolTest", now; - - std::vector v; - v.push_back(true); - v.push_back(false); - v.push_back(false); - v.push_back(true); - - try { session() << "INSERT INTO BoolTest VALUES (?)", use(v), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - v.clear(); - session() << "SELECT * FROM BoolTest", into(v), now; - - assertTrue (4 == v.size()); - std::vector::iterator it = v.begin(); - std::vector::iterator end = v.end(); - int t = 0; - for (; it != end; ++it) - t += *it ? 1 : 0; - assertTrue (2 == t); - - try { session() << "SELECT * FROM BoolTest WHERE b = ?", out(v), now; fail("must fail"); } - catch (BindingException&) { } - - try { session() << "SELECT * FROM BoolTest WHERE b = ?", io(v), now; fail("must fail"); } - catch (BindingException&) { } - - RecordSet rset(session(), "SELECT * FROM BoolTest"); - - t = 0; - for (int i = 0; i < 4; ++i) - t += rset.value(0, i) ? 1 : 0; - assertTrue (2 == t); -} - - -void SQLExecutor::asynchronous(int rowCount) -{ - Session tmp = session(); - - std::vector data(rowCount); - Statement stmt = (tmp << "INSERT INTO Strings VALUES(?)", use(data)); - Statement::Result result = stmt.executeAsync(); - assertTrue (!stmt.isAsync()); - result.wait(); - - Statement stmt1 = (tmp << "SELECT * FROM Strings", into(data), async, now); - assertTrue (stmt1.isAsync()); - assertTrue (stmt1.wait() == rowCount); - - // +++ if this part of the test case fails, increase the rowCount until achieved - // that first execute is still executing when the second one is called - stmt1.execute(); - try { - stmt1.execute(); - fail ("execute() must fail"); - } catch (InvalidAccessException&) - { - stmt1.wait(); - stmt1.execute(); - stmt1.wait(); - } - // --- - - stmt = tmp << "SELECT * FROM Strings", into(data), async, now; - assertTrue (stmt.isAsync()); - stmt.wait(); - assertTrue (stmt.execute() == 0); - - // +++ if this part of the test case fails, increase the rowCount until achieved - // that first execute is still executing when the second one is called - try { - result = stmt.executeAsync(); - fail ("executeAsync() must fail"); - } catch (InvalidAccessException&) - { - assertTrue (stmt.isAsync()); - stmt.wait(); - result = stmt.executeAsync(); - } - // --- - - assertTrue (stmt.wait() == rowCount); - assertTrue (result.data() == rowCount); - stmt.setAsync(false); - assertTrue (!stmt.isAsync()); - assertTrue (stmt.execute() == rowCount); - - stmt = tmp << "SELECT * FROM Strings", into(data), sync, now; - assertTrue (!stmt.isAsync()); - assertTrue (stmt.wait() == 0); - assertTrue (stmt.execute() == rowCount); - result = stmt.executeAsync(); - assertTrue (!stmt.isAsync()); - result.wait(); - assertTrue (result.data() == rowCount); - - assertTrue (0 == rowCount % 10); - int step = (int) (rowCount/10); - data.clear(); - Statement stmt2 = (tmp << "SELECT * FROM Strings", into(data), async, limit(step)); - assertTrue (data.size() == 0); - assertTrue (!stmt2.done()); - std::size_t rows = 0; - - for (int i = 0; !stmt2.done(); i += step) - { - stmt2.execute(); - rows = stmt2.wait(); - assertTrue (step == rows); - assertTrue (step + i == data.size()); - } - assertTrue (stmt2.done()); - assertTrue (rowCount == data.size()); - - stmt2 = tmp << "SELECT * FROM Strings", reset; - assertTrue (!stmt2.isAsync()); - assertTrue ("deque" == stmt2.getStorage()); - assertTrue (stmt2.execute() == rowCount); -} - - void SQLExecutor::any() { Any i = 42; @@ -3967,799 +1085,3 @@ void SQLExecutor::any() assertTrue (AnyCast(s) == "42"); #endif } - - -void SQLExecutor::dynamicAny() -{ - Var i = 42; - Var f = 42.5; - Var s = "42"; - - Session tmp = session(); - tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now; - - int count = 0; - tmp << "SELECT COUNT(*) FROM Anys", into(count), now; - assertTrue (1 == count); - - i = 0; - f = 0.0; - s = std::string(""); - tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now; - assertTrue (42 == i); - assertTrue (42.5 == f); - assertTrue ("42" == s); -} - - -void SQLExecutor::multipleResults(const std::string& sql) -{ - typedef Tuple Person; - std::vector people; - people.push_back(Person("Simpson", "Homer", "Springfield", 42)); - people.push_back(Person("Simpson", "Marge", "Springfield", 38)); - people.push_back(Person("Simpson", "Bart", "Springfield", 10)); - people.push_back(Person("Simpson", "Lisa", "Springfield", 8)); - people.push_back(Person("Simpson", "Maggie", "Springfield", 3)); - session() << "INSERT INTO Person VALUES (?, ?, ?, ?)", use(people), now; - - Person pHomer; - int aHomer = 42, aLisa = 8; - Poco::UInt32 aBart = 0; - - Poco::UInt32 pos1 = 1; - int pos2 = 2; - std::vector people2; - Statement stmt(session()); - stmt << sql, into(pHomer, from(0)), use(aHomer) - , into(aBart, pos1) - , into(people2, from(pos2)), use(aLisa), use(aHomer); - - assertTrue (4 == stmt.execute()); - assertTrue (Person("Simpson", "Homer", "Springfield", 42) == pHomer); - assertTrue (10 == aBart); - assertTrue (2 == people2.size()); - assertTrue (Person("Simpson", "Lisa", "Springfield", 8) == people2[0]); - assertTrue (Person("Simpson", "Homer", "Springfield", 42) == people2[1]); -} - - -void SQLExecutor::sqlChannel(const std::string& connect) -{ - try - { - AutoPtr pChannel = new SQLChannel(Poco::Data::ODBC::Connector::KEY, connect, "TestSQLChannel"); - Stopwatch sw; sw.start(); - while (!pChannel->isRunning()) - { - Thread::sleep(10); - if (sw.elapsedSeconds() > 3) - fail ("SQLExecutor::sqlLogger(): SQLChannel timed out"); - } - - pChannel->setProperty("bulk", "true"); - pChannel->setProperty("keep", "2 seconds"); - - Message msgInf("InformationSource", "a Informational async message", Message::PRIO_INFORMATION); - pChannel->log(msgInf); - while (pChannel->logged() != 1) Thread::sleep(10); - - Message msgWarn("WarningSource", "b Warning async message", Message::PRIO_WARNING); - pChannel->log(msgWarn); - while (pChannel->logged() != 2) Thread::sleep(10); - - Message msgInfS("InformationSource", "c Informational sync message", Message::PRIO_INFORMATION); - pChannel->log(msgInfS); - while (pChannel->logged() != 3) Thread::sleep(10); - Message msgWarnS("WarningSource", "d Warning sync message", Message::PRIO_WARNING); - pChannel->log(msgWarnS); - while (pChannel->logged() != 4) Thread::sleep(10); - - RecordSet rs(session(), "SELECT * FROM T_POCO_LOG ORDER by Text"); - size_t rc = rs.rowCount(); - assertTrue (4 == rc); - assertTrue ("InformationSource" == rs["Source"]); - assertTrue ("a Informational async message" == rs["Text"]); - rs.moveNext(); - assertTrue ("WarningSource" == rs["Source"]); - assertTrue ("b Warning async message" == rs["Text"]); - rs.moveNext(); - assertTrue ("InformationSource" == rs["Source"]); - assertTrue ("c Informational sync message" == rs["Text"]); - rs.moveNext(); - assertTrue ("WarningSource" == rs["Source"]); - assertTrue ("d Warning sync message" == rs["Text"]); - - Thread::sleep(3000); // give it time to archive - - Message msgInfA("InformationSource", "e Informational sync message", Message::PRIO_INFORMATION); - pChannel->log(msgInfA); - while (pChannel->logged() != 5) Thread::sleep(10); - Message msgWarnA("WarningSource", "f Warning sync message", Message::PRIO_WARNING); - pChannel->log(msgWarnA); - while (pChannel->logged() != 6) Thread::sleep(10); - - RecordSet rs1(session(), "SELECT * FROM T_POCO_LOG_ARCHIVE"); - assertTrue (4 == rs1.rowCount()); - - pChannel->setProperty("keep", ""); - assertTrue ("forever" == pChannel->getProperty("keep")); - RecordSet rs2(session(), "SELECT * FROM T_POCO_LOG ORDER by Text"); - assertTrue (2 == rs2.rowCount()); - assertTrue ("InformationSource" == rs2["Source"]); - assertTrue ("e Informational sync message" == rs2["Text"]); - rs2.moveNext(); - assertTrue ("WarningSource" == rs2["Source"]); - assertTrue ("f Warning sync message" == rs2["Text"]); - } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("sqlChannel()"); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("sqlChannel()"); } -} - - -void SQLExecutor::sqlLogger(const std::string& connect) -{ - try - { - Logger& root = Logger::root(); - SQLChannel* pSQLChannel = new SQLChannel(Poco::Data::ODBC::Connector::KEY, connect, "TestSQLChannel"); - Stopwatch sw; sw.start(); - while (!pSQLChannel->isRunning()) - { - Thread::sleep(10); - if (sw.elapsedSeconds() > 3) - fail ("SQLExecutor::sqlLogger(): SQLChannel timed out"); - } - - root.setChannel(pSQLChannel); - root.setLevel(Message::PRIO_INFORMATION); - - root.information("a Informational message"); - root.warning("b Warning message"); - root.debug("Debug message"); - - while (pSQLChannel->logged() != 2) Thread::sleep(100); - RecordSet rs(session(), "SELECT * FROM T_POCO_LOG ORDER by Text"); - assertTrue (2 == rs.rowCount()); - assertTrue ("TestSQLChannel" == rs["Source"]); - assertTrue ("a Informational message" == rs["Text"]); - rs.moveNext(); - assertTrue ("TestSQLChannel" == rs["Source"]); - assertTrue ("b Warning message" == rs["Text"]); - } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("sqlLogger()"); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("sqlLogger()"); } -} - - -void SQLExecutor::setTransactionIsolation(Session& session, Poco::UInt32 ti) -{ - if (session.hasTransactionIsolation(ti)) - { - std::string funct = "setTransactionIsolation()"; - - try - { - Transaction t(session, false); - t.setIsolation(ti); - - assertTrue (ti == t.getIsolation()); - assertTrue (t.isIsolation(ti)); - - assertTrue (ti == session.getTransactionIsolation()); - assertTrue (session.isTransactionIsolation(ti)); - } - catch(Poco::Exception& e){ std::cout << funct << ':' << e.displayText() << std::endl;} - } - else - { - std::cerr << '[' << name() << ']' << " Warning, transaction isolation not supported: "; - switch (ti) - { - case Session::TRANSACTION_READ_COMMITTED: - std::cerr << "READ COMMITTED"; break; - case Session::TRANSACTION_READ_UNCOMMITTED: - std::cerr << "READ UNCOMMITTED"; break; - case Session::TRANSACTION_REPEATABLE_READ: - std::cerr << "REPEATABLE READ"; break; - case Session::TRANSACTION_SERIALIZABLE: - std::cerr << "SERIALIZABLE"; break; - default: - std::cerr << "UNKNOWN"; break; - } - std::cerr << std::endl; - } -} - - -void SQLExecutor::autoCommit(const std::string& connect) -{ - 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() -{ - 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); - - 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); - assertTrue (session().getFeature("autoCommit")); - assertTrue (!session().isTransaction()); - - session().begin(); - assertTrue (session().isTransaction()); - assertTrue (!session().getFeature("autoCommit")); - - // changing 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) { } - // make sure nothing was changed ... - assertTrue (!session().getFeature("autoCommit")); - // but setting it to its current state is allowed (no-op) - session().setFeature("autoCommit", false); - assertTrue (!session().getFeature("autoCommit")); - - 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); - - session() << "SELECT COUNT(*) FROM Person", into(count), now; - assertTrue (2 == count); - assertTrue (session().isTransaction()); - session().rollback(); - assertTrue (!session().isTransaction()); - - stmt.wait(); - assertTrue (0 == locCount); - stmt.reset(session()); - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (0 == count); - assertTrue (!session().isTransaction()); - - session().begin(); - session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; - assertTrue (session().isTransaction()); - - stmt = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now); - - session().commit(); - assertTrue (!session().isTransaction()); - - stmt.wait(); - assertTrue (2 == locCount); - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (2 == count); - // end autoCommit = true - - // restore the original transaction state - session().setFeature("autoCommit", autoCommit); -} - - -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); -#ifndef POCO_DATA_NO_SQL_PARSER - assertTrue (local.isTransaction()); - - // autocommit is invalid for session in transaction ... - try - { - local.setFeature("autoCommit", true); - fail ("must fail on autocommit setting during transaction", __LINE__); - } - catch(const Poco::InvalidAccessException& e) { } - - // but setting it to its current state is allowed (no-op) - local.setFeature("autoCommit", false); - - assertTrue (!session().isTransaction()); -#else - session().commit(); -#endif // POCO_DATA_NO_SQL_PARSER - 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); -#ifndef POCO_DATA_NO_SQL_PARSER - assertTrue (local.isTransaction()); - assertTrue (!session().isTransaction()); -#else - session().commit(); -#endif - - 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); -#ifndef POCO_DATA_NO_SQL_PARSER - session().commit(); - local.commit(); -#endif - session().setFeature("autoCommit", autoCommit); -} - - -void SQLExecutor::transaction(const std::string& connect) -{ - if (!session().canTransact()) - { - std::cout << "Session not transaction-capable." << std::endl; - return; - } - - 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); - else if (local.hasTransactionIsolation(Session::TRANSACTION_READ_COMMITTED)) - setTransactionIsolation(local, Session::TRANSACTION_READ_COMMITTED); - - std::string funct = "transaction()"; - 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); - assertTrue (!session().isTransaction()); - session().setFeature("autoCommit", false); - assertTrue (!session().isTransaction()); - session().setTransactionIsolation(Session::TRANSACTION_READ_COMMITTED); - - { - Transaction trans(session()); - assertTrue (trans.isActive()); - assertTrue (session().isTransaction()); - - session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; - - assertTrue (session().isTransaction()); - assertTrue (trans.isActive()); - - session() << "SELECT COUNT(*) FROM Person", into(count), now; - assertTrue (2 == count); - assertTrue (session().isTransaction()); - assertTrue (trans.isActive()); - } - assertTrue (!session().isTransaction()); - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (0 == count); - assertTrue (!session().isTransaction()); - session().commit(); - - { - Transaction trans(session()); - session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; - - Statement stmt1 = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now); - - assertTrue (session().isTransaction()); - assertTrue (trans.isActive()); - trans.commit(); - assertTrue (!session().isTransaction()); - assertTrue (!trans.isActive()); - - stmt1.wait(); - assertTrue (2 == locCount); - } - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (2 == count); - - session() << "DELETE FROM Person", now; - - Statement stmt1 = (local << "SELECT count(*) FROM Person", into(locCount), async, now); - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (0 == count); - try - { - stmt1.wait(5000); - if (local.getTransactionIsolation() == Session::TRANSACTION_READ_UNCOMMITTED) - assertTrue (0 == locCount); - } catch (TimeoutException&) - { std::cerr << '[' << name() << ']' << " Warning: async query timed out." << std::endl; } - session().commit(); - // repeat for those that don't support uncommitted read isolation - if (local.getTransactionIsolation() == Session::TRANSACTION_READ_COMMITTED) - { - stmt1.wait(); - local << "SELECT count(*) FROM Person", into(locCount), now; - assertTrue (0 == locCount); - } - - std::string sql1 = format("INSERT INTO Person VALUES ('%s','%s','%s',%d)", lastNames[0], firstNames[0], addresses[0], ages[0]); - std::string sql2 = format("INSERT INTO Person VALUES ('%s','%s','%s',%d)", lastNames[1], firstNames[1], addresses[1], ages[1]); - std::vector sql; - sql.push_back(sql1); - sql.push_back(sql2); - - Transaction trans(session()); - - trans.execute(sql1, false); - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (1 == count); - trans.execute(sql2, false); - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (2 == count); - - Statement stmt2 = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now); - - trans.rollback(); - - stmt2.wait(); - assertTrue (0 == locCount); - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (0 == count); - - trans.execute(sql); - - Statement stmt3 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now); - assertTrue (2 == locCount); - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (2 == count); - session().commit(); - - // restore the original transaction state - session().setFeature("autoCommit", autoCommit); - setTransactionIsolation(session(), ti); -} - - -struct TestCommitTransactor -{ - void operator () (Session& session) const - { - session << "INSERT INTO Person VALUES ('lastName','firstName','address',10)", now; - } -}; - - -struct TestRollbackTransactor -{ - void operator () (Session& session) const - { - session << "INSERT INTO Person VALUES ('lastName','firstName','address',10)", now; - throw Poco::Exception("test"); - } -}; - - -void SQLExecutor::transactor() -{ - std::string funct = "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); - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (1 == count); - - session() << "DELETE FROM Person", now; session().commit(); - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (0 == count); - - try - { - TestRollbackTransactor rt; - Transaction t(session(), rt); - fail ("must fail"); - } catch (Poco::Exception&) { } - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (0 == count); - - try - { - TestRollbackTransactor rt; - Transaction t(session()); - t.transact(rt); - fail ("must fail"); - } catch (Poco::Exception&) { } - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (0 == count); - - try - { - TestRollbackTransactor rt; - Transaction t(session(), false); - t.transact(rt); - fail ("must fail"); - } catch (Poco::Exception&) { } - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (0 == count); - - try - { - TestRollbackTransactor rt; - Transaction t(session(), true); - t.transact(rt); - fail ("must fail"); - } catch (Poco::Exception&) { } - - session() << "SELECT count(*) FROM Person", into(count), now; - assertTrue (0 == count); - session().commit(); - - // restore the original transaction state - session().setFeature("autoCommit", autoCommit); - setTransactionIsolation(session(), ti); -} - - -void SQLExecutor::nullable() -{ - try { session() << "INSERT INTO NullableTest VALUES(NULL, NULL, NULL, NULL)", now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("nullable()"); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("nullable()"); } - - Nullable i = 1; - Nullable f = 1.5; - Nullable s = std::string("abc"); - Nullable d = DateTime(); - - assertTrue (!i.isNull()); - assertTrue (!f.isNull()); - assertTrue (!s.isNull()); - assertTrue (!d.isNull()); - - session() << "SELECT EmptyString, EmptyInteger, EmptyFloat, EmptyDateTime FROM NullableTest", into(s), into(i), into(f), into(d), now; - - assertTrue (i.isNull()); - assertTrue (f.isNull()); - assertTrue (s.isNull()); - assertTrue (d.isNull()); - - RecordSet rs(session(), "SELECT * FROM NullableTest"); - - rs.moveFirst(); - assertTrue (rs.isNull("EmptyString")); - assertTrue (rs.isNull("EmptyInteger")); - assertTrue (rs.isNull("EmptyFloat")); - assertTrue (rs.isNull("EmptyDateTime")); - - Var di = 1; - Var df = 1.5; - Var ds = "abc"; - Var dd = DateTime(); - - assertTrue (!di.isEmpty()); - assertTrue (!df.isEmpty()); - assertTrue (!ds.isEmpty()); - assertTrue (!dd.isEmpty()); - - Statement stmt = (session() << "SELECT EmptyString, EmptyInteger, EmptyFloat, EmptyDateTime FROM NullableTest", into(ds), into(di), into(df), into(dd), now); - - assertTrue (di.isEmpty()); - assertTrue (df.isEmpty()); - assertTrue (ds.isEmpty()); - assertTrue (dd.isEmpty()); -} - - -void SQLExecutor::reconnect() -{ - std::string funct = "reconnect()"; - std::string lastName = "lastName"; - std::string firstName("firstName"); - std::string address("Address"); - int age = 133132; - int count = 0; - std::string result; - - try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age), now; } - catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } - catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - - count = 0; - 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); } - assertTrue (count == 1); - - assertTrue (session().isConnected()); - session().close(); - assertTrue (!session().isConnected()); - try - { - session() << "SELECT LastName FROM Person", into(result), now; - fail ("must fail"); - } - catch(NotConnectedException&){ } - assertTrue (!session().isConnected()); - - session().open(); - assertTrue (session().isConnected()); - try { session() << "SELECT Age 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); } - assertTrue (count == age); - assertTrue (session().isConnected()); -} - - -void SQLExecutor::unicode(const std::string& dbConnString) -{ - const unsigned char supp[] = { 0x41, 0x42, 0xf0, 0x90, 0x82, 0xa4, 0xf0, 0xaf, 0xa6, 0xa0, 0xf0, 0xaf, 0xa8, 0x9d, 0x00 }; - std::string text((const char*) supp); - - UTF16String wtext; - Poco::UnicodeConverter::convert(text, wtext); - session() << "INSERT INTO UnicodeTable VALUES (?)", use(wtext), now; - wtext.clear(); - text.clear(); - session() << "SELECT str FROM UnicodeTable", into(wtext), now; - Poco::UnicodeConverter::convert(wtext, text); - assertTrue (text == std::string((const char*)supp)); -} - - -void SQLExecutor::encoding(const std::string& dbConnString) -{ - try - { - const unsigned char latinChars[] = { 'g', 252, 'n', 't', 'e', 'r', 0 }; - const unsigned char utf8Chars[] = { 'g', 195, 188, 'n', 't', 'e', 'r', 0 }; - std::string latinText((const char*)latinChars); - std::string utf8TextIn((const char*)utf8Chars); - - session(true) << "INSERT INTO Latin1Table VALUES (?)", use(utf8TextIn), now; - - std::string latinTextOut; - session() << "SELECT str FROM Latin1Table", into(latinTextOut), now; - assertTrue(latinText == latinTextOut); - - std::string utf8TextOut; - session(true) << "SELECT str FROM Latin1Table", into(utf8TextOut), now; - assertTrue(utf8TextIn == utf8TextOut); - - const unsigned char latinChars2[] = { 'G', 220, 'N', 'T', 'E', 'R', 0 }; - const unsigned char utf8Chars2[] = { 'G', 195, 156, 'N', 'T', 'E', 'R', 0 }; - std::string latinText2 = (const char*)latinChars2; - std::string utf8TextIn2 = (const char*)utf8Chars2; - - session(true) << "INSERT INTO Latin1Table VALUES (?)", use(utf8TextIn2), now; - - std::vector textOutVec; - session() << "SELECT str FROM Latin1Table", into(textOutVec), now; - assertTrue(textOutVec.size() == 2); - assertTrue(textOutVec[0] == latinText); - assertTrue(textOutVec[1] == latinText2); - - textOutVec.clear(); - session(true) << "SELECT str FROM Latin1Table", into(textOutVec), now; - assertTrue(textOutVec.size() == 2); - assertTrue(textOutVec[0] == utf8TextIn); - assertTrue(textOutVec[1] == utf8TextIn2); - } - catch (Poco::Exception& ex) - { - std::cout << ex.displayText() << std::endl; - throw; - } - catch (std::exception& ex) - { - std::cout << ex.what() << std::endl; - throw; - } -} diff --git a/Data/ODBC/testsuite/src/SQLExecutor.h b/Data/ODBC/testsuite/src/SQLExecutor.h index a9771e0c9..815d937d7 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.h +++ b/Data/ODBC/testsuite/src/SQLExecutor.h @@ -20,6 +20,7 @@ #include "Poco/Data/Session.h" #include "Poco/Data/BulkExtraction.h" #include "Poco/Data/BulkBinding.h" +#include "Poco/Data/Test/SQLExecutor.h" #include "Poco/NumberFormatter.h" #include "Poco/String.h" #include "Poco/Exception.h" @@ -534,21 +535,498 @@ private: Poco::Data::Session& session(bool enc = false); Poco::Data::Session* _pSession; Poco::Data::Session* _pEncSession; + Poco::Data::Test::SQLExecutor _dataExecutor; }; -inline Poco::Data::Session& SQLExecutor::session(bool enc) +inline void SQLExecutor::sessionPool(const std::string& connectString, int minSessions, int maxSessions, int idleTime, int timeout) { - if (!enc) - { - poco_check_ptr(_pSession); - return *_pSession; - } - else - { - poco_check_ptr(_pEncSession); - return *_pEncSession; - } + _dataExecutor.sessionPool("ODBC", connectString, minSessions, maxSessions, idleTime, timeout); +} + + +inline void SQLExecutor::zeroRows() +{ + _dataExecutor.zeroRows(); +} + + +inline void SQLExecutor::simpleAccess() +{ + _dataExecutor.simpleAccess(); +} + + +inline void SQLExecutor::complexType() +{ + _dataExecutor.complexType(); +} + + +inline void SQLExecutor::complexTypeTuple() +{ + _dataExecutor.complexTypeTuple(); +} + + +inline void SQLExecutor::simpleAccessVector() +{ + _dataExecutor.simpleAccessVector(); +} + + +inline void SQLExecutor::complexTypeVector() +{ + _dataExecutor.complexTypeVector(); +} + + +inline void SQLExecutor::sharedPtrComplexTypeVector() +{ + _dataExecutor.sharedPtrComplexTypeVector(); +} + + +inline void SQLExecutor::autoPtrComplexTypeVector() +{ + _dataExecutor.autoPtrComplexTypeVector(); +} + + +inline void SQLExecutor::insertVector() +{ + _dataExecutor.insertVector(); +} + + +inline void SQLExecutor::insertEmptyVector() +{ + _dataExecutor.insertEmptyVector(); +} + + +inline void SQLExecutor::simpleAccessList() +{ + _dataExecutor.simpleAccessList(); +} + + +inline void SQLExecutor::complexTypeList() +{ + _dataExecutor.complexTypeList(); +} + + +inline void SQLExecutor::insertList() +{ + _dataExecutor.insertList(); +} + + +inline void SQLExecutor::insertEmptyList() +{ + _dataExecutor.insertEmptyList(); +} + + +inline void SQLExecutor::simpleAccessDeque() +{ + _dataExecutor.simpleAccessDeque(); +} + + +inline void SQLExecutor::complexTypeDeque() +{ + _dataExecutor.complexTypeDeque(); +} + + +inline void SQLExecutor::insertDeque() +{ + _dataExecutor.insertDeque(); +} + + +inline void SQLExecutor::insertEmptyDeque() +{ + _dataExecutor.insertEmptyDeque(); +} + + +inline void SQLExecutor::affectedRows(const std::string& whereClause) +{ + _dataExecutor.affectedRows(); +} + + +inline void SQLExecutor::insertSingleBulk() +{ + _dataExecutor.insertSingleBulk(); +} + + +inline void SQLExecutor::floats() +{ + _dataExecutor.floats(); +} + + +inline void SQLExecutor::doubles() +{ + _dataExecutor.doubles(); +} + + +inline void SQLExecutor::uuids() +{ + _dataExecutor.uuids(); +} + + +inline void SQLExecutor::insertSingleBulkVec() +{ + _dataExecutor.insertSingleBulkVec(); +} + + +inline void SQLExecutor::limits() +{ + _dataExecutor.limits(); +} + + +inline void SQLExecutor::limitZero() +{ + _dataExecutor.limitZero(); +} + + +inline void SQLExecutor::limitOnce() +{ + _dataExecutor.limitOnce(); +} + + +inline void SQLExecutor::limitPrepare() +{ + _dataExecutor.limitPrepare(); +} + + +inline void SQLExecutor::prepare() +{ + _dataExecutor.prepare(); +} + + +inline void SQLExecutor::doBulkPerformance(Poco::UInt32 size) +{ + _dataExecutor.doBulkPerformance(size); +} + + +inline void SQLExecutor::setSimple() +{ + _dataExecutor.setSimple(); +} + + +inline void SQLExecutor::setComplex() +{ + _dataExecutor.setComplex(); +} + + +inline void SQLExecutor::setComplexUnique() +{ + _dataExecutor.setComplexUnique(); +} + +inline void SQLExecutor::multiSetSimple() +{ + _dataExecutor.multiSetSimple(); +} + + +inline void SQLExecutor::multiSetComplex() +{ + _dataExecutor.multiSetComplex(); +} + + +inline void SQLExecutor::mapComplex() +{ + _dataExecutor.mapComplex(); +} + + +inline void SQLExecutor::mapComplexUnique() +{ + _dataExecutor.mapComplexUnique(); +} + + +inline void SQLExecutor::multiMapComplex() +{ + _dataExecutor.multiMapComplex(); +} + + +inline void SQLExecutor::selectIntoSingle() +{ + _dataExecutor.selectIntoSingle(); +} + + +inline void SQLExecutor::selectIntoSingleStep() +{ + _dataExecutor.selectIntoSingleStep(); +} + + +inline void SQLExecutor::selectIntoSingleFail() +{ + _dataExecutor.selectIntoSingleFail(); +} + + +inline void SQLExecutor::lowerLimitOk() +{ + _dataExecutor.lowerLimitOk(); +} + + +inline void SQLExecutor::singleSelect() +{ + _dataExecutor.singleSelect(); +} + + +inline void SQLExecutor::lowerLimitFail() +{ + _dataExecutor.lowerLimitFail(); +} + + +inline void SQLExecutor::combinedLimits() +{ + _dataExecutor.combinedLimits(); +} + + + +inline void SQLExecutor::ranges() +{ + _dataExecutor.ranges(); +} + + +inline void SQLExecutor::combinedIllegalLimits() +{ + _dataExecutor.combinedIllegalLimits(); +} + + +inline void SQLExecutor::illegalRange() +{ + _dataExecutor.illegalRange(); +} + + +inline void SQLExecutor::emptyDB() +{ + _dataExecutor.emptyDB(); +} + + +inline void SQLExecutor::blob(int bigSize, const std::string& blobPlaceholder) +{ + _dataExecutor.blob(bigSize, blobPlaceholder); +} + + +inline void SQLExecutor::blobStmt() +{ + _dataExecutor.blobStmt(); +} + + +inline void SQLExecutor::recordSet() +{ + _dataExecutor.recordSet(); +} + + +inline void SQLExecutor::dateTime() +{ + _dataExecutor.dateTime(); +} + + +inline void SQLExecutor::date() +{ + _dataExecutor.date(); +} + + +inline void SQLExecutor::time() +{ + _dataExecutor.time(); +} + + +inline void SQLExecutor::tuples() +{ + _dataExecutor.tuples(); +} + +inline void SQLExecutor::tupleVector() +{ + _dataExecutor.tupleVector(); +} + + +inline void SQLExecutor::internalExtraction() +{ + _dataExecutor.internalExtraction(); +} + + +inline void SQLExecutor::filter(const std::string& query, const std::string& intFldName) +{ + _dataExecutor.filter(); +} + + +inline void SQLExecutor::internalBulkExtraction() +{ + _dataExecutor.internalBulkExtraction(); +} + + +inline void SQLExecutor::internalBulkExtractionUTF16() +{ + _dataExecutor.internalBulkExtractionUTF16(); +} + + +inline void SQLExecutor::internalStorageType() +{ + _dataExecutor.internalStorageType(); +} + + +inline void SQLExecutor::nulls() +{ + _dataExecutor.nulls(); +} + + +inline void SQLExecutor::rowIterator() +{ + _dataExecutor.rowIterator(); +} + + +inline void SQLExecutor::stdVectorBool() +{ + _dataExecutor.stdVectorBool(); +} + + +inline void SQLExecutor::asynchronous(int rowCount) +{ + _dataExecutor.asynchronous(); +} + + +inline void SQLExecutor::dynamicAny() +{ + _dataExecutor.dynamicAny(); +} + + +inline void SQLExecutor::multipleResults(const std::string& sql) +{ + _dataExecutor.multipleResults(); +} + + +inline void SQLExecutor::sqlChannel(const std::string& connect) +{ + _dataExecutor.sqlChannel("odbc", connect); +} + + +inline void SQLExecutor::sqlLogger(const std::string& connect) +{ + _dataExecutor.sqlLogger("odbc", connect); +} + + +inline void SQLExecutor::setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti) +{ + _dataExecutor.setTransactionIsolation(session, ti); +} + + +inline void SQLExecutor::autoCommit(const std::string&) +{ + _dataExecutor.autoCommit(); +} + + +inline void SQLExecutor::transactionIsolation() +{ + _dataExecutor.transactionIsolation(); +} + + +inline void SQLExecutor::sessionTransaction(const std::string& connect) +{ + _dataExecutor.sessionTransaction("odbc", connect); +} + + +inline void SQLExecutor::sessionTransactionNoAutoCommit(const std::string& connect) +{ + _dataExecutor.sessionTransactionNoAutoCommit("odbc", connect); +} + + +inline void SQLExecutor::transaction(const std::string& connect) +{ + _dataExecutor.transaction("odbc", connect); +} + + +inline void SQLExecutor::transactor() +{ + _dataExecutor.transactor(); +} + + +inline void SQLExecutor::nullable() +{ + _dataExecutor.nullable(); +} + + +inline void SQLExecutor::reconnect() +{ + _dataExecutor.reconnect(); +} + + +inline void SQLExecutor::unicode(const std::string& dbConnString) +{ + _dataExecutor.unicode(dbConnString); +} + + +inline void SQLExecutor::encoding(const std::string& dbConnString) +{ + _dataExecutor.encoding(dbConnString); } diff --git a/Data/testsuite/Makefile b/Data/testsuite/Makefile index bd7adb02b..b60c67fe0 100644 --- a/Data/testsuite/Makefile +++ b/Data/testsuite/Makefile @@ -1,30 +1,11 @@ # # Makefile # -# Makefile for Poco Data testsuite +# Makefile for Poco Data Tests # -include $(POCO_BASE)/build/rules/global - -ifeq ($(findstring SunOS,$(POCO_HOST_OSNAME)),SunOS) - POCO_SUN_FORTE = $(findstring SunOS-SunForte, $(POCO_CONFIG)) - POCO_SUN_STUDIO = $(findstring SunOS-SunStudio, $(POCO_CONFIG)) - ifneq (,$or ($(POCO_SUN_FORTE), $(POCO_SUN_STUDIO))) - CXXFLAGS += -erroff=hidevf - endif -endif - -objects = DataTestSuite Driver \ - DataTest SessionPoolTest \ - Binder Extractor Preparator SessionImpl Connector TestStatementImpl - -ifndef POCO_DATA_NO_SQL_PARSER - objects += SQLParserTest - target_includes = $(POCO_BASE)/Data/src -endif - -target = testrunner -target_version = 1 -target_libs = PocoData PocoFoundation CppUnit - -include $(POCO_BASE)/build/rules/exec +.PHONY: projects +clean distclean all: projects +projects: + $(MAKE) -f Makefile-testrunner $(MAKECMDGOALS) + $(MAKE) -f Makefile-library $(MAKECMDGOALS) diff --git a/Data/testsuite/Makefile-library b/Data/testsuite/Makefile-library new file mode 100644 index 000000000..afc360f99 --- /dev/null +++ b/Data/testsuite/Makefile-library @@ -0,0 +1,21 @@ +# +# Makefile +# +# Makefile for Poco Data testsuite library +# + +include $(POCO_BASE)/build/rules/global + +objects = SQLExecutor + +target_includes = $(POCO_BASE)/Data/testsuite/include +ifndef POCO_DATA_NO_SQL_PARSER + objects += SQLParserTest + target_includes += $(POCO_BASE)/Data/src +endif + +target = PocoDataTest +target_version = 1 +target_libs = PocoData PocoFoundation CppUnit + +include $(POCO_BASE)/build/rules/lib diff --git a/Data/testsuite/Makefile-testrunner b/Data/testsuite/Makefile-testrunner new file mode 100644 index 000000000..9964afe64 --- /dev/null +++ b/Data/testsuite/Makefile-testrunner @@ -0,0 +1,31 @@ +# +# Makefile +# +# Makefile for Poco Data testsuite +# + +include $(POCO_BASE)/build/rules/global + +ifeq ($(findstring SunOS,$(POCO_HOST_OSNAME)),SunOS) + POCO_SUN_FORTE = $(findstring SunOS-SunForte, $(POCO_CONFIG)) + POCO_SUN_STUDIO = $(findstring SunOS-SunStudio, $(POCO_CONFIG)) + ifneq (,$or ($(POCO_SUN_FORTE), $(POCO_SUN_STUDIO))) + CXXFLAGS += -erroff=hidevf + endif +endif + +objects = DataTestSuite Driver \ + DataTest SessionPoolTest Binder Extractor Preparator \ + SessionImpl Connector TestStatementImpl + +target_includes = $(POCO_BASE)/Data/testsuite/include +ifndef POCO_DATA_NO_SQL_PARSER + objects += SQLParserTest + target_includes += $(POCO_BASE)/Data/src +endif + +target = testrunner +target_version = 1 +target_libs = PocoData PocoFoundation CppUnit + +include $(POCO_BASE)/build/rules/exec diff --git a/Data/testsuite/include/Poco/Data/Test/SQLExecutor.h b/Data/testsuite/include/Poco/Data/Test/SQLExecutor.h new file mode 100644 index 000000000..3b88b113b --- /dev/null +++ b/Data/testsuite/include/Poco/Data/Test/SQLExecutor.h @@ -0,0 +1,241 @@ +// +// SQLExecutor.h +// +// Definition of the SQLExecutor class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Data_SQLExecutor_INCLUDED +#define Data_SQLExecutor_INCLUDED + + +#include "Poco/Data/Data.h" +#include "Poco/Data/Session.h" +#include "Poco/Data/BulkExtraction.h" +#include "Poco/Data/BulkBinding.h" +#include "Poco/NumberFormatter.h" +#include "Poco/String.h" +#include "Poco/Exception.h" +#include + + +#define poco_data_using_keywords using Poco::Data::Keywords::now; \ + using Poco::Data::Keywords::into; \ + using Poco::Data::Keywords::use; \ + using Poco::Data::Keywords::bulk; \ + using Poco::Data::Keywords::limit; \ + using Poco::Data::DataException; \ + using Poco::Data::CLOB; + + +namespace Poco { +namespace Data { +namespace Test { + + +class SQLExecutor: public CppUnit::TestCase +{ +public: + enum DataBinding + { + PB_IMMEDIATE, + PB_AT_EXEC + }; + + enum DataExtraction + { + DE_MANUAL, + DE_BOUND + }; + + SQLExecutor(const std::string& name, Poco::Data::Session* pSession, Poco::Data::Session* pEncSession = 0); + ~SQLExecutor(); + + template + void connection(C& c, const std::string& connectString) + { + assertFalse (c.isConnected()); + assertTrue (c.connect(connectString, 5)); + assertTrue (c.isConnected()); + assertTrue (c.getTimeout() == 5); + c.setTimeout(6); + assertTrue (c.getTimeout() == 6); + assertTrue (c.disconnect()); + assertFalse (c.isConnected()); + assertTrue (c.connect(connectString)); + assertTrue (c.isConnected()); + try + { + c.connect(); + fail ("Connection attempt must fail when already connected"); + } + catch(const Poco::InvalidAccessException&){} + assertTrue (c.disconnect()); + assertFalse (c.isConnected()); + try + { + c.connect(); + fail ("Connection attempt with empty string must fail"); + } + catch(const Poco::InvalidArgumentException&){} + } + + void session(const std::string& connector, const std::string& connectString, int timeout); + void sessionPool(const std::string& connector, const std::string& connectString, int minSessions, int maxSessions, int idleTime, int timeout); + + void execute(const std::string& sql); + /// Execute a query. + + void zeroRows(); + void simpleAccess(); + void complexType(); + void complexTypeTuple(); + + void simpleAccessVector(); + void complexTypeVector(); + void sharedPtrComplexTypeVector(); + void autoPtrComplexTypeVector(); + void insertVector(); + void insertEmptyVector(); + + void simpleAccessList(); + void complexTypeList(); + void insertList(); + void insertEmptyList(); + + void simpleAccessDeque(); + void complexTypeDeque(); + void insertDeque(); + void insertEmptyDeque(); + + void affectedRows(const std::string& whereClause = ""); + + void insertSingleBulk(); + void insertSingleBulkVec(); + + void limits(); + void limitOnce(); + void limitPrepare(); + void limitZero(); + void prepare(); + + void doBulkPerformance(Poco::UInt32 size); + + void setSimple(); + void setComplex(); + void setComplexUnique(); + void multiSetSimple(); + void multiSetComplex(); + void mapComplex(); + void mapComplexUnique(); + void multiMapComplex(); + void selectIntoSingle(); + void selectIntoSingleStep(); + void selectIntoSingleFail(); + void lowerLimitOk(); + void lowerLimitFail(); + void combinedLimits(); + void combinedIllegalLimits(); + void ranges(); + void illegalRange(); + void singleSelect(); + void emptyDB(); + + void blob(int bigSize = 1024, const std::string& blobPlaceholder = "?"); + + template + void blobContainer(int size) + { + poco_data_using_keywords; + + std::string funct = "blobContainer()"; + C1 lastName(size, "lastname"); + C1 firstName(size, "firstname"); + C1 address(size, "Address"); + C2 img(size, CLOB("0123456789", 10)); + int count = 0; + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(img), now; } + catch(DataException& ce){ std::cout << ce.displayText() << std::endl; fail (funct, __LINE__, __FILE__); } + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce){ std::cout << ce.displayText() << std::endl; fail (funct, __LINE__, __FILE__); } + assert (count == size); + + C2 res; + try { session() << "SELECT Image FROM Person", into(res), now; } + catch(DataException& ce){ std::cout << ce.displayText() << std::endl; fail (funct, __LINE__, __FILE__); } + assert (res.size() == img.size()); + assert (res == img); + } + + void blobStmt(); + void recordSet(); + + void dateTime(); + void date(); + void time(); + void floats(); + void doubles(); + void uuids(); + void tuples(); + void tupleVector(); + + void internalExtraction(); + void filter(const std::string& query = + "SELECT * FROM Vectors ORDER BY int0 ASC", + const std::string& intFldName = "int0"); + + void internalBulkExtraction(); + void internalBulkExtractionUTF16(); + void internalStorageType(); + void nulls(); + void rowIterator(); + void stdVectorBool(); + + void asynchronous(int rowCount = 500); + + void any(); + void dynamicAny(); + + void multipleResults(const std::string& sql = + "SELECT * FROM Person WHERE Age = ?; " + "SELECT Age FROM Person WHERE FirstName = 'Bart'; " + "SELECT * FROM Person WHERE Age = ? OR Age = ? ORDER BY Age;"); + + void sqlChannel(const std::string& connector, const std::string& connect); + void sqlLogger(const std::string& connector, const std::string& connect); + + void autoCommit(); + void transactionIsolation(); + + void sessionTransaction(const std::string& connector, const std::string& connect); + void sessionTransactionNoAutoCommit(const std::string& connector, const std::string& connect); + void transaction(const std::string& connector, const std::string& connect); + void transactor(); + void nullable(); + + void unicode(const std::string& dbConnString); + void encoding(const std::string& dbConnString); + + void reconnect(); + + Poco::Data::Session& session(bool enc = false); + void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti); + +private: + static const std::string MULTI_INSERT; + static const std::string MULTI_SELECT; + + Poco::Data::Session* _pSession; + Poco::Data::Session* _pEncSession; +}; + + +} } } // Poco::Data::Test + + +#endif // Data_SQLExecutor_INCLUDED diff --git a/Data/testsuite/src/SQLExecutor.cpp b/Data/testsuite/src/SQLExecutor.cpp new file mode 100644 index 000000000..e319a019a --- /dev/null +++ b/Data/testsuite/src/SQLExecutor.cpp @@ -0,0 +1,4382 @@ +// +// SQLExecutor.cpp +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "CppUnit/TestCase.h" +#include "Poco/Data/Test/SQLExecutor.h" +#include "Poco/String.h" +#include "Poco/Format.h" +#include "Poco/Tuple.h" +#include "Poco/Nullable.h" +#include "Poco/Any.h" +#include "Poco/Dynamic/Var.h" +#include "Poco/DateTime.h" +#include "Poco/Stopwatch.h" +#include "Poco/NumberFormatter.h" +#include "Poco/Thread.h" +#include "Poco/Logger.h" +#include "Poco/Message.h" +#include "Poco/RefCountedObject.h" +#include "Poco/AutoPtr.h" +#include "Poco/SharedPtr.h" +#include "Poco/Exception.h" +#include "Poco/Data/Date.h" +#include "Poco/Data/Time.h" +#include "Poco/Data/LOB.h" +#include "Poco/Data/Session.h" +#include "Poco/Data/SessionPool.h" +#include "Poco/Data/StatementImpl.h" +#include "Poco/Data/RecordSet.h" +#include "Poco/Data/RowIterator.h" +#include "Poco/Data/RowFilter.h" +#include "Poco/Data/BulkExtraction.h" +#include "Poco/Data/BulkBinding.h" +#include "Poco/Data/SQLChannel.h" +#include "Poco/Data/Transaction.h" +#include "Poco/UnicodeConverter.h" +#include "Poco/UTFString.h" +#include +#include +#include +#include + + +using namespace Poco::Data::Keywords; +using Poco::Data::Session; +using Poco::Data::SessionPool; +using Poco::Data::Statement; +using Poco::Data::RecordSet; +using Poco::Data::Column; +using Poco::Data::Row; +using Poco::Data::RowFilter; +using Poco::Data::RowIterator; +using Poco::Data::SQLChannel; +using Poco::Data::LimitException; +using Poco::Data::BindingException; +using Poco::Data::CLOB; +using Poco::Data::Date; +using Poco::Data::Time; +using Poco::Data::Transaction; +using Poco::Data::NotConnectedException; +using Poco::Data::DataException; +using Poco::format; +using Poco::Tuple; +using Poco::Nullable; +using Poco::Any; +using Poco::AnyCast; +using Poco::Dynamic::Var; +using Poco::DateTime; +using Poco::Stopwatch; +using Poco::NumberFormatter; +using Poco::AutoPtr; +using Poco::Thread; +using Poco::Logger; +using Poco::Message; +using Poco::NotFoundException; +using Poco::InvalidAccessException; +using Poco::InvalidArgumentException; +using Poco::NotImplementedException; +using Poco::BadCastException; +using Poco::RangeException; +using Poco::TimeoutException; +using Poco::UnicodeConverter; +using Poco::UTF16String; +using Poco::UTF32String; + +namespace { + + +struct Person +{ + std::string lastName; + std::string firstName; + std::string address; + int age; + Person(){age = 0;} + Person(const std::string& ln, const std::string& fn, const std::string& adr, int a):lastName(ln), firstName(fn), address(adr), age(a) + { + } + bool operator==(const Person& other) const + { + return lastName == other.lastName && firstName == other.firstName && address == other.address && age == other.age; + } + + bool operator < (const Person& p) const + { + if (age < p.age) + return true; + if (lastName < p.lastName) + return true; + if (firstName < p.firstName) + return true; + return (address < p.address); + } + + const std::string& operator () () const + /// This method is required so we can extract data to a map! + { + // we choose the lastName as the key + return lastName; + } +}; + + +struct RefCountedPerson : public Poco::RefCountedObject +{ + std::string lastName; + std::string firstName; + std::string address; + int age; + RefCountedPerson(){age = 0;} + RefCountedPerson(const std::string& ln, const std::string& fn, const std::string& adr, int a):lastName(ln), firstName(fn), address(adr), age(a) + { + } + bool operator==(const Person& other) const + { + return lastName == other.lastName && firstName == other.firstName && address == other.address && age == other.age; + } + + bool operator < (const RefCountedPerson& p) const + { + if (age < p.age) + return true; + if (lastName < p.lastName) + return true; + if (firstName < p.firstName) + return true; + return (address < p.address); + } + + const std::string& operator () () const + /// This method is required so we can extract data to a map! + { + // we choose the lastName as the key + return lastName; + } + +private: + RefCountedPerson(const RefCountedPerson &); + RefCountedPerson& operator = (const RefCountedPerson&); +}; + + +} // namespace + + +namespace Poco { +namespace Data { + + +template <> +class TypeHandler +{ +public: + static void bind(std::size_t pos, + const Person& obj, + AbstractBinder::Ptr pBinder, + AbstractBinder::Direction dir = AbstractBinder::PD_IN) + { + // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3)) + poco_assert_dbg (!pBinder.isNull()); + pBinder->bind(pos++, obj.lastName, dir); + pBinder->bind(pos++, obj.firstName, dir); + pBinder->bind(pos++, obj.address, dir); + pBinder->bind(pos++, obj.age, dir); + } + + static void prepare(std::size_t pos, const Person& obj, AbstractPreparator::Ptr pPrepare) + { + // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3)) + poco_assert_dbg (!pPrepare.isNull()); + pPrepare->prepare(pos++, obj.lastName); + pPrepare->prepare(pos++, obj.firstName); + pPrepare->prepare(pos++, obj.address); + pPrepare->prepare(pos++, obj.age); + } + + static std::size_t size() + { + return 4; + } + + static void extract(std::size_t pos, Person& obj, const Person& defVal, AbstractExtractor::Ptr pExt) + { + poco_assert_dbg (!pExt.isNull()); + if (!pExt->extract(pos++, obj.lastName)) + obj.lastName = defVal.lastName; + if (!pExt->extract(pos++, obj.firstName)) + obj.firstName = defVal.firstName; + if (!pExt->extract(pos++, obj.address)) + obj.address = defVal.address; + if (!pExt->extract(pos++, obj.age)) + obj.age = defVal.age; + } + +private: + TypeHandler(const TypeHandler&); + TypeHandler& operator=(const TypeHandler&); +}; + + +template <> +class TypeHandler +{ +public: + static void bind(std::size_t pos, + const RefCountedPerson& obj, + AbstractBinder::Ptr pBinder, + AbstractBinder::Direction dir = AbstractBinder::PD_IN) + { + // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3)) + poco_assert_dbg (!pBinder.isNull()); + pBinder->bind(pos++, obj.lastName, dir); + pBinder->bind(pos++, obj.firstName, dir); + pBinder->bind(pos++, obj.address, dir); + pBinder->bind(pos++, obj.age, dir); + } + + static void prepare(std::size_t pos, RefCountedPerson& obj, AbstractPreparator::Ptr pPrepare) + { + // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3)) + poco_assert_dbg (!pPrepare.isNull()); + pPrepare->prepare(pos++, obj.lastName); + pPrepare->prepare(pos++, obj.firstName); + pPrepare->prepare(pos++, obj.address); + pPrepare->prepare(pos++, obj.age); + } + + static std::size_t size() + { + return 4; + } + + static void extract(std::size_t pos, RefCountedPerson& obj, const RefCountedPerson& defVal, AbstractExtractor::Ptr pExt) + { + poco_assert_dbg (!pExt.isNull()); + if (!pExt->extract(pos++, obj.lastName)) + obj.lastName = defVal.lastName; + if (!pExt->extract(pos++, obj.firstName)) + obj.firstName = defVal.firstName; + if (!pExt->extract(pos++, obj.address)) + obj.address = defVal.address; + if (!pExt->extract(pos++, obj.age)) + obj.age = defVal.age; + } + +private: + TypeHandler(const TypeHandler&); + TypeHandler& operator=(const TypeHandler&); +}; + + +namespace Test { + + +const std::string SQLExecutor::MULTI_INSERT = + "INSERT INTO Test VALUES ('1', 2, 3.5);" + "INSERT INTO Test VALUES ('2', 3, 4.5);" + "INSERT INTO Test VALUES ('3', 4, 5.5);" + "INSERT INTO Test VALUES ('4', 5, 6.5);" + "INSERT INTO Test VALUES ('5', 6, 7.5);"; + +const std::string SQLExecutor::MULTI_SELECT = + "SELECT * FROM Test WHERE First = '1';" + "SELECT * FROM Test WHERE First = '2';" + "SELECT * FROM Test WHERE First = '3';" + "SELECT * FROM Test WHERE First = '4';" + "SELECT * FROM Test WHERE First = '5';"; + + +SQLExecutor::SQLExecutor(const std::string& name, Poco::Data::Session* pSession, Poco::Data::Session* pEncSession): + CppUnit::TestCase(name), + _pSession(pSession), + _pEncSession(pEncSession) +{ +} + + +SQLExecutor::~SQLExecutor() +{ +} + + +Poco::Data::Session& SQLExecutor::session(bool enc) +{ + if (!enc) + { + poco_check_ptr(_pSession); + return *_pSession; + } + else + { + poco_check_ptr(_pEncSession); + return *_pEncSession; + } +} + + +void SQLExecutor::execute(const std::string& sql) +{ + try { session() << sql, now; } catch(DataException& ce){ std::cout << ce.displayText() << std::endl; fail (sql, __LINE__, __FILE__); } +} + + +void SQLExecutor::session(const std::string& connector, const std::string& connectString, int timeout) +{ + Poco::Data::Session s(connector, connectString, timeout); + assertTrue (s.isConnected()); + s.close(); + assertTrue (!s.isConnected()); + s.open(); + assertTrue (s.isConnected()); + s.reconnect(); + assertTrue (s.isConnected()); + s.close(); + assertTrue (!s.isConnected()); + s.reconnect(); + assertTrue (s.isConnected()); +} + + +void SQLExecutor::sessionPool(const std::string& connector, const std::string& connectString, int minSessions, int maxSessions, int idleTime, int timeout) +{ + assertTrue (minSessions <= maxSessions); + + SessionPool sp(connector, connectString, minSessions, maxSessions, idleTime, timeout); + assertEqual (0, sp.allocated()); + assertEqual (maxSessions, sp.available()); + Session s1 = sp.get(); + assertEqual (minSessions, sp.allocated()); + assertEqual (maxSessions-1, sp.available()); + s1 = sp.get(); + assertEqual (2, sp.allocated()); + assertEqual (maxSessions-1, sp.available()); + { + Session s2 = sp.get(); + assertEqual (2, sp.allocated()); + assertEqual (maxSessions-2, sp.available()); + } + assertEqual (2, sp.allocated()); + assertEqual (maxSessions-1, sp.available()); + + Thread::sleep(idleTime + 500); + assertEqual (maxSessions-minSessions, sp.available()); + + try + { + sp.setFeature("autoBind"s, true); + fail("SessionPool must throw on setFeature after the first session was created.", __LINE__, __FILE__); + } catch(const Poco::InvalidAccessException&) {} + try + { + sp.setProperty("storage"s, "deque"s); + fail("SessionPool must throw on valid setProperty after the first session was created.", __LINE__, __FILE__); + } catch(const Poco::InvalidAccessException&) {} + try + { + sp.setFeature("bulk"s, true); + fail("SessionPool must throw on valid setFeature after the first session was created.", __LINE__, __FILE__); + } catch(const Poco::InvalidAccessException&) {} + + std::vector sessions; + for (int i = 0; i < maxSessions-minSessions; ++i) + { + sessions.push_back(sp.get()); + } + + try + { + Session s = sp.get(); + fail("SessionPool must throw when no sesions available.", __LINE__, __FILE__); + } catch(const Poco::Data::SessionPoolExhaustedException&) {} + + sp.shutdown(); + try + { + Session s = sp.get(); + fail("SessionPool that was shut down must throw on get.", __LINE__, __FILE__); + } catch(const Poco::InvalidAccessException&) {} + + { + SessionPool pool(connector, connectString, 1, 4, 2, 10); + + try { pool.getFeature("g1"); fail ("getting an unsuported feature must fail", __LINE__, __FILE__); } + catch ( Poco::NotFoundException& ) { } + + try { pool.getProperty("r1"); fail ("getting an unsuported property must fail", __LINE__, __FILE__); } + catch ( Poco::NotFoundException& ) { } + + assertTrue (pool.capacity() == 4); + assertTrue (pool.allocated() == 0); + assertTrue (pool.idle() == 0); + assertTrue (pool.connTimeout() == 10); + assertTrue (pool.available() == 4); + assertTrue (pool.dead() == 0); + assertTrue (pool.allocated() == pool.used() + pool.idle()); + Session s1(pool.get()); + + try { pool.setFeature("f1", true); fail ("setting an unsuported feature must fail", __LINE__, __FILE__); } + catch (Poco::InvalidAccessException&) { } + catch (Poco::NotImplementedException&) { } + catch (Poco::Data::NotSupportedException&) { } + + try { pool.setProperty("p1", 1); fail ("setting an unsuported property must fail", __LINE__, __FILE__); } + catch (Poco::InvalidAccessException&) { } + catch (Poco::NotImplementedException&) { } + catch (Poco::Data::NotSupportedException&) { } + + assertTrue (pool.capacity() == 4); + assertTrue (pool.allocated() == 1); + assertTrue (pool.idle() == 0); + assertTrue (pool.connTimeout() == 10); + assertTrue (pool.available() == 3); + assertTrue (pool.dead() == 0); + assertTrue (pool.allocated() == pool.used() + pool.idle()); + + Session s2(pool.get()); + assertTrue (pool.capacity() == 4); + assertTrue (pool.allocated() == 2); + assertTrue (pool.idle() == 0); + assertTrue (pool.connTimeout() == 10); + assertTrue (pool.available() == 2); + assertTrue (pool.dead() == 0); + assertTrue (pool.allocated() == pool.used() + pool.idle()); + + Session s4(pool.get()); + 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()); + + Session s5(pool.get()); + assertTrue (pool.capacity() == 4); + assertTrue (pool.allocated() == 4); + assertTrue (pool.idle() == 0); + assertTrue (pool.connTimeout() == 10); + assertTrue (pool.available() == 0); + assertTrue (pool.dead() == 0); + assertTrue (pool.allocated() == pool.used() + pool.idle()); + + try + { + Session s6(pool.get()); + fail("pool exhausted - must throw", __LINE__, __FILE__); + } + catch (Poco::Data::SessionPoolExhaustedException&) { } + + s5.close(); + assertTrue (pool.capacity() == 4); + assertTrue (pool.allocated() == 4); + assertTrue (pool.idle() == 1); + assertTrue (pool.connTimeout() == 10); + assertTrue (pool.available() == 1); + assertTrue (pool.dead() == 0); + assertTrue (pool.allocated() == pool.used() + pool.idle()); + + try + { + s5 << "DROP TABLE IF EXISTS Test", now; + fail("session unusable - must throw", __LINE__, __FILE__); + } + catch (Poco::Data::SessionUnavailableException&) { } + + s4.close(); + assertTrue (pool.capacity() == 4); + assertTrue (pool.allocated() == 4); + assertTrue (pool.idle() == 2); + assertTrue (pool.connTimeout() == 10); + assertTrue (pool.available() == 2); + assertTrue (pool.dead() == 0); + assertTrue (pool.allocated() == pool.used() + pool.idle()); + + Thread::sleep(5000); // time to clean up idle sessions + + assertTrue (pool.capacity() == 4); + assertTrue (pool.allocated() == 2); + assertTrue (pool.idle() == 0); + assertTrue (pool.connTimeout() == 10); + assertTrue (pool.available() == 2); + assertTrue (pool.dead() == 0); + assertTrue (pool.allocated() == pool.used() + pool.idle()); + + Session s6(pool.get()); + + 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()); + + s6.close(); + 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()); + + assertTrue (pool.isActive()); + pool.shutdown(); + assertTrue (!pool.isActive()); + try + { + Session s7(pool.get()); + fail("pool shut down - must throw", __LINE__, __FILE__); + } + catch (InvalidAccessException&) { } + + assertTrue (pool.capacity() == 4); + assertTrue (pool.allocated() == 0); + assertTrue (pool.idle() == 0); + assertTrue (pool.connTimeout() == 10); + assertTrue (pool.available() == 0); + assertTrue (pool.dead() == 0); + assertTrue (pool.allocated() == 0); + assertTrue (pool.used() == 0); + assertTrue (pool.idle() == 0); + } +} + + +void SQLExecutor::zeroRows() +{ + Statement stmt = (session() << "SELECT * FROM Person WHERE 0 = 1"); + assertTrue (0 == stmt.execute()); +} + + +void SQLExecutor::simpleAccess() +{ + std::string lastName = "lastName"; + std::string firstName("firstName"); + std::string address("Address"); + int age = 133132; + int count = 0; + std::string result; + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 1); + + try { session() << "SELECT LastName FROM Person", into(result), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (lastName == result); + + try { session() << "SELECT Age FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == age); +} + + +void SQLExecutor::complexType() +{ + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(p1), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(p2), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + Person c1; + try { session() << "SELECT * FROM Person WHERE LastName = 'LN1'", into(c1), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (c1 == p1); +} + + +void SQLExecutor::complexTypeTuple() +{ + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + + Tuple t(p1,p2); + try { *_pSession << "INSERT INTO Person VALUES(?,?,?,?,?,?,?,?)", use(t), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + Tuple ret; + assertTrue (ret != t); + try { *_pSession << "SELECT * FROM Person", into(ret), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (ret == t); +} + + +void SQLExecutor::simpleAccessVector() +{ + 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; + std::string result; + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::vector lastNamesR; + std::vector firstNamesR; + std::vector addressesR; + std::vector agesR; + try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (ages == agesR); + assertTrue (lastNames == lastNamesR); + assertTrue (firstNames == firstNamesR); + assertTrue (addresses == addressesR); +} + + +void SQLExecutor::complexTypeVector() +{ + std::vector people; + people.push_back(Person("LN1", "FN1", "ADDR1", 1)); + people.push_back(Person("LN2", "FN2", "ADDR2", 2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::vector result; + try { session() << "SELECT * FROM Person", into(result), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result == people); +} + + +void SQLExecutor::sharedPtrComplexTypeVector() +{ + std::vector > people; + people.push_back(new Person("LN1", "FN1", "ADDR1", 1)); + people.push_back(new Person("LN2", "FN2", "ADDR2", 2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::vector result; + try { session() << "SELECT * FROM Person", into(result), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (2 == result.size()); + assertTrue (result[0] == *people[0]); + assertTrue (result[1] == *people[1]); +} + + +void SQLExecutor::autoPtrComplexTypeVector() +{ + std::vector > people; + people.push_back(new RefCountedPerson("LN1", "FN1", "ADDR1", 1)); + people.push_back(new RefCountedPerson("LN2", "FN2", "ADDR2", 2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::vector result; + try { session() << "SELECT * FROM Person", into(result), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (2 == result.size()); + assertTrue (result[0].address == people[0]->address); + assertTrue (result[0].age == people[0]->age); + assertTrue (result[0].firstName == people[0]->firstName); + assertTrue (result[0].lastName == people[0]->lastName); + assertTrue (result[1].address == people[1]->address); + assertTrue (result[1].age == people[1]->age); + assertTrue (result[1].firstName == people[1]->firstName); + assertTrue (result[1].lastName == people[1]->lastName); +} + + +void SQLExecutor::insertVector() +{ + std::vector str; + str.push_back("s1"); + str.push_back("s2"); + str.push_back("s3"); + str.push_back("s3"); + int count = 100; + + { + Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(str))); + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 0); + + try { stmt.execute(); } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 4); + } + count = 0; + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 4); +} + + +void SQLExecutor::insertEmptyVector() +{ + std::vector str; + + try + { + session() << "INSERT INTO Strings VALUES (?)", use(str), now; + fail("empty collections should not work", __LINE__, __FILE__); + } catch (Poco::Exception&) + { + } +} + + +void SQLExecutor::simpleAccessList() +{ + std::list lastNames; + std::list firstNames; + std::list addresses; + std::list 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; + std::string result; + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::list lastNamesR; + std::list firstNamesR; + std::list addressesR; + std::list agesR; + try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (ages == agesR); + assertTrue (lastNames == lastNamesR); + assertTrue (firstNames == firstNamesR); + assertTrue (addresses == addressesR); +} + + +void SQLExecutor::complexTypeList() +{ + std::list people; + people.push_back(Person("LN1", "FN1", "ADDR1", 1)); + people.push_back(Person("LN2", "FN2", "ADDR2", 2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::list result; + try { session() << "SELECT * FROM Person", into(result), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result == people); +} + + +void SQLExecutor::insertList() +{ + std::list str; + str.push_back("s1"); + str.push_back("s2"); + str.push_back("s3"); + str.push_back("s3"); + int count = 100; + + { + Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(str))); + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 0); + + try { stmt.execute(); } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 4); + } + count = 0; + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 4); +} + + +void SQLExecutor::insertEmptyList() +{ + std::list str; + + try + { + session() << "INSERT INTO Strings VALUES (?)", use(str), now; + fail("empty collections should not work"); + } catch (Poco::Exception&) + { + } +} + + +void SQLExecutor::simpleAccessDeque() +{ + std::deque lastNames; + std::deque firstNames; + std::deque addresses; + std::deque 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; + std::string result; + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::deque lastNamesR; + std::deque firstNamesR; + std::deque addressesR; + std::deque agesR; + try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (ages == agesR); + assertTrue (lastNames == lastNamesR); + assertTrue (firstNames == firstNamesR); + assertTrue (addresses == addressesR); +} + + +void SQLExecutor::complexTypeDeque() +{ + std::deque people; + people.push_back(Person("LN1", "FN1", "ADDR1", 1)); + people.push_back(Person("LN2", "FN2", "ADDR2", 2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::deque result; + try { session() << "SELECT * FROM Person", into(result), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result == people); +} + + +void SQLExecutor::insertDeque() +{ + std::deque str; + str.push_back("s1"); + str.push_back("s2"); + str.push_back("s3"); + str.push_back("s3"); + int count = 100; + + { + Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(str))); + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 0); + + try { stmt.execute(); } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 4); + } + count = 0; + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 4); +} + + +void SQLExecutor::insertEmptyDeque() +{ + std::deque str; + + try + { + session() << "INSERT INTO Strings VALUES (?)", use(str), now; + fail("empty collections should not work"); + } catch (Poco::Exception&) + { + } +} + + +void SQLExecutor::affectedRows(const std::string& whereClause) +{ + std::vector str; + str.push_back("s1"); + str.push_back("s2"); + str.push_back("s3"); + str.push_back("s3"); + int count = 100; + + Statement stmt1((session() << "INSERT INTO Strings VALUES(?)", use(str))); + session() << "SELECT COUNT(*) FROM Strings", into(count), now; + assertTrue (count == 0); + assertTrue (4 == stmt1.execute()); + session() << "SELECT COUNT(*) FROM Strings", into(count), now; + assertTrue (count == 4); + + Statement stmt2(session() << "UPDATE Strings SET str = 's4' WHERE str = 's3'"); + assertTrue (2 == stmt2.execute()); + + Statement stmt3(session() << "DELETE FROM Strings WHERE str = 's1'"); + assertTrue (1 == stmt3.execute()); + + std::string sql; + format(sql, "DELETE FROM Strings %s", whereClause); + Statement stmt4(session() << sql); + assertTrue (3 == stmt4.execute()); +} + + +void SQLExecutor::insertSingleBulk() +{ + int x = 0; + Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(x))); + + for (x = 0; x < 100; ++x) + { + std::size_t i = stmt.execute(); + assertTrue (1 == i); + } + int count = 0; + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 100); + + try { session() << "SELECT SUM(str) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == ((0+99)*100/2)); +} + + +void SQLExecutor::floats() +{ + float data = 1.5f; + float ret = 0.0f; + + try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 1); + + try { session() << "SELECT str FROM Strings", into(ret), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (ret == data); +} + + +void SQLExecutor::doubles() +{ + double data = 1.5; + double ret = 0.0; + + try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 1); + + try { session() << "SELECT str FROM Strings", into(ret), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (ret == data); +} + + +void SQLExecutor::uuids() +{ + Poco::UUID data("49cf6461-9b62-4163-9659-5472ef73153d"); + Poco::UUID ret; + + try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 1); + + try { session() << "SELECT str FROM Strings", into(ret), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (ret == data); +} + + +void SQLExecutor::insertSingleBulkVec() +{ + std::vector data; + + for (int x = 0; x < 100; ++x) + data.push_back(x); + + Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(data))); + stmt.execute(); + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + assertTrue (count == 100); + try { session() << "SELECT SUM(str) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == ((0+99)*100/2)); +} + + +void SQLExecutor::limits() +{ + std::vector data; + for (int x = 0; x < 100; ++x) + { + data.push_back(x); + } + + try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + std::vector retData; + try { session() << "SELECT * FROM Strings", into(retData), limit(50), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (retData.size() == 50); + for (int x = 0; x < 50; ++x) + { + assertTrue (data[x] == retData[x]); + } +} + + +void SQLExecutor::limitZero() +{ + std::vector data; + for (int x = 0; x < 100; ++x) + { + data.push_back(x); + } + + try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + std::vector retData; + try { session() << "SELECT * FROM Strings", into(retData), limit(0), now; }// stupid test, but at least we shouldn't crash + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (retData.size() == 0); +} + + +void SQLExecutor::limitOnce() +{ + std::vector data; + for (int x = 0; x < 101; ++x) + { + data.push_back(x); + } + + try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + std::vector retData; + Statement stmt = (session() << "SELECT * FROM Strings", into(retData), limit(50), now); + assertTrue (!stmt.done()); + assertTrue (retData.size() == 50); + stmt.execute(); + assertTrue (!stmt.done()); + assertTrue (retData.size() == 100); + stmt.execute(); + assertTrue (stmt.done()); + assertTrue (retData.size() == 101); + + for (int x = 0; x < 101; ++x) + { + assertTrue (data[x] == retData[x]); + } +} + + +void SQLExecutor::limitPrepare() +{ + std::vector data; + for (int x = 0; x < 100; ++x) + { + data.push_back(x); + } + + try + { + Statement stmt = (session() << "INSERT INTO Strings VALUES (?)", use(data)); + assertTrue (100 == stmt.execute()); + } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + std::vector retData; + Statement stmt = (session() << "SELECT * FROM Strings", into(retData), limit(50)); + assertTrue (retData.size() == 0); + assertTrue (!stmt.done()); + + try { stmt.execute(); } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (!stmt.done()); + assertTrue (retData.size() == 50); + + try { stmt.execute(); } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (stmt.done()); + assertTrue (retData.size() == 100); + + try { stmt.execute(); } // will restart execution! catch(DataException& ce) + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (!stmt.done()); + assertTrue (retData.size() == 150); + for (int x = 0; x < 150; ++x) + { + assertTrue (data[x%100] == retData[x]); + } +} + + +void SQLExecutor::prepare() +{ + std::vector data; + for (int x = 0; x < 100; x += 2) + { + data.push_back(x); + } + + { + Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(data))); + } + + // stmt should not have been executed when destroyed + int count = 100; + try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 0); +} + + +void SQLExecutor::doBulkPerformance(Poco::UInt32 size) +{ + std::vector ints(size, 1); + std::vector strings(size, "abc"); + std::vector floats(size, .5); + std::vector dateTimes(size); + + Stopwatch sw; + try + { + sw.start(); + session() << "INSERT INTO MiscTest (First, Third, Fourth, Fifth) VALUES (?,?,?,?)", + use(strings), + use(ints), + use(floats), + use(dateTimes), now; + sw.stop(); + } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + double time = sw.elapsed() / 1000.0; + + try { session() << "DELETE FROM MiscTest", now; } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try + { + sw.restart(); + session() << "INSERT INTO MiscTest (First, Third, Fourth, Fifth) VALUES (?,?,?,?)", + use(strings, bulk), + use(ints, bulk), + use(floats, bulk), + use(dateTimes, bulk), now; + sw.stop(); + } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + double bulkTime = sw.elapsed() / 1000.0; + + double speedup; + if (0.0 == bulkTime) + { + if (0.0 == time) speedup = 1.0; + else speedup = time; + } + else + speedup = time / bulkTime; + + std::cout << "INSERT => Size:" << size + << ", Time: " << time + << ", Bulk Time: " << bulkTime + << " [ms], Speedup: " << speedup + << 'x' << std::endl; + + ints.clear(); + strings.clear(); + floats.clear(); + dateTimes.clear(); + + try + { + sw.restart(); + session() << "SELECT First, Third, Fourth, Fifth FROM MiscTest", + into(strings), + into(ints), + into(floats), + into(dateTimes), + now; + sw.stop(); + } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + time = sw.elapsed() / 1000.0; + + assertTrue (ints.size() == size); + + ints.clear(); + strings.clear(); + floats.clear(); + dateTimes.clear(); + + try + { + sw.restart(); + session() << "SELECT First, Third, Fourth, Fifth FROM MiscTest", + into(strings, bulk(size)), + into(ints, bulk(size)), + into(floats, bulk(size)), + into(dateTimes, bulk(size)), + now; + sw.stop(); + } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + bulkTime = sw.elapsed() / 1000.0; + + assertTrue (ints.size() == size); + + if (0.0 == bulkTime) + { + if (0.0 == time) speedup = 1.0; + else speedup = time; + } + else + speedup = time / bulkTime; + + std::cout << "SELECT => Size:" << size + << ", Time: " << time + << ", Bulk Time: " << bulkTime + << " [ms], Speedup: " << speedup + << 'x' << std::endl; +} + + +void SQLExecutor::setSimple() +{ + std::set lastNames; + std::set firstNames; + std::set addresses; + std::set ages; + std::string tableName("Person"); + lastNames.insert("LN1"); + lastNames.insert("LN2"); + firstNames.insert("FN1"); + firstNames.insert("FN2"); + addresses.insert("ADDR1"); + addresses.insert("ADDR2"); + ages.insert(1); + ages.insert(2); + int count = 0; + std::string result; + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::set lastNamesR; + std::set firstNamesR; + std::set addressesR; + std::set agesR; + try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (ages == agesR); + assertTrue (lastNames == lastNamesR); + assertTrue (firstNames == firstNamesR); + assertTrue (addresses == addressesR); +} + + +void SQLExecutor::setComplex() +{ + std::set people; + people.insert(Person("LN1", "FN1", "ADDR1", 1)); + people.insert(Person("LN2", "FN2", "ADDR2", 2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::set result; + try { session() << "SELECT * FROM Person", into(result), now; } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result == people); +} + + +void SQLExecutor::setComplexUnique() +{ + std::vector people; + Person p1("LN1", "FN1", "ADDR1", 1); + people.push_back(p1); + people.push_back(p1); + people.push_back(p1); + people.push_back(p1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.push_back(p2); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 5); + + std::set result; + try { session() << "SELECT * FROM Person", into(result), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result.size() == 2); + assertTrue (*result.begin() == p1); + assertTrue (*++result.begin() == p2); +} + +void SQLExecutor::multiSetSimple() +{ + std::multiset lastNames; + std::multiset firstNames; + std::multiset addresses; + std::multiset ages; + std::string tableName("Person"); + lastNames.insert("LN1"); + lastNames.insert("LN2"); + firstNames.insert("FN1"); + firstNames.insert("FN2"); + addresses.insert("ADDR1"); + addresses.insert("ADDR2"); + ages.insert(1); + ages.insert(2); + int count = 0; + std::string result; + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::multiset lastNamesR; + std::multiset firstNamesR; + std::multiset addressesR; + std::multiset agesR; + try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (ages.size() == agesR.size()); + assertTrue (lastNames.size() == lastNamesR.size()); + assertTrue (firstNames.size() == firstNamesR.size()); + assertTrue (addresses.size() == addressesR.size()); +} + + +void SQLExecutor::multiSetComplex() +{ + std::multiset people; + Person p1("LN1", "FN1", "ADDR1", 1); + people.insert(p1); + people.insert(p1); + people.insert(p1); + people.insert(p1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(p2); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 5); + + std::multiset result; + try { session() << "SELECT * FROM Person", into(result), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result.size() == people.size()); +} + + +void SQLExecutor::mapComplex() +{ + std::map people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN2", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + + std::map result; + try { session() << "SELECT * FROM Person", into(result), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result == people); +} + + +void SQLExecutor::mapComplexUnique() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN2", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 5); + + std::map result; + try { session() << "SELECT * FROM Person", into(result), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result.size() == 2); +} + + +void SQLExecutor::multiMapComplex() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN2", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 5); + + std::multimap result; + try { session() << "SELECT * FROM Person", into(result), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result.size() == people.size()); +} + + +void SQLExecutor::selectIntoSingle() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN2", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + Person result; + try { session() << "SELECT * FROM Person ORDER BY LastName", into(result), limit(1), now; }// will return 1 object into one single result + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result == p1); +} + + +void SQLExecutor::selectIntoSingleStep() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN2", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + Person result; + Statement stmt = (session() << "SELECT * FROM Person", into(result), limit(1)); + stmt.execute(); + assertTrue (result == p1); + assertTrue (!stmt.done()); + stmt.execute(); + assertTrue (result == p2); + assertTrue (stmt.done()); +} + + +void SQLExecutor::selectIntoSingleFail() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN2", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), limit(2, true), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + Person result; + try + { + session() << "SELECT * FROM Person", into(result), limit(1, true), now; // will fail now + fail("hardLimit is set: must fail", __LINE__, __FILE__); + } catch(Poco::Data::LimitException&) + { + } +} + + +void SQLExecutor::lowerLimitOk() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + Person result; + try + { + session() << "SELECT * FROM Person", into(result), lowerLimit(2), now; // will return 2 objects into one single result but only room for one! + fail("Not enough space for results", __LINE__, __FILE__); + } catch(Poco::Exception&) + { + } +} + + +void SQLExecutor::singleSelect() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + Person result; + Statement stmt = (session() << "SELECT * FROM Person", into(result), limit(1)); + stmt.execute(); + assertTrue (result == p1); + assertTrue (!stmt.done()); + stmt.execute(); + assertTrue (result == p2); + assertTrue (stmt.done()); +} + + +void SQLExecutor::lowerLimitFail() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + Person result; + try + { + session() << "SELECT * FROM Person", into(result), lowerLimit(3), now; // will fail + fail("should fail. not enough data", __LINE__, __FILE__); + } catch(Poco::Exception&) + { + } +} + + +void SQLExecutor::combinedLimits() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + std::vector result; + try { session() << "SELECT * FROM Person", into(result), lowerLimit(2), upperLimit(2), now; }// will return 2 objects + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result.size() == 2); + assertTrue (result[0] == p1); + assertTrue (result[1] == p2); +} + + + +void SQLExecutor::ranges() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + std::vector result; + try { session() << "SELECT * FROM Person", into(result), range(2, 2), now; }// will return 2 objects + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (result.size() == 2); + assertTrue (result[0] == p1); + assertTrue (result[1] == p2); +} + + +void SQLExecutor::combinedIllegalLimits() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + Person result; + try + { + session() << "SELECT * FROM Person", into(result), lowerLimit(3), upperLimit(2), now; + fail("lower > upper is not allowed", __LINE__, __FILE__); + } catch(LimitException&) + { + } +} + + +void SQLExecutor::illegalRange() +{ + std::multimap people; + Person p1("LN1", "FN1", "ADDR1", 1); + Person p2("LN2", "FN2", "ADDR2", 2); + people.insert(std::make_pair("LN1", p1)); + people.insert(std::make_pair("LN1", p2)); + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 2); + Person result; + try + { + session() << "SELECT * FROM Person", into(result), range(3, 2), now; + fail("lower > upper is not allowed", __LINE__, __FILE__); + } catch(LimitException&) + { + } +} + + +void SQLExecutor::emptyDB() +{ + int count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 0); + + Person result; + Statement stmt = (session() << "SELECT * FROM Person", into(result), limit(1)); + stmt.execute(); + assertTrue (result.firstName.empty()); + assertTrue (stmt.done()); +} + + +void SQLExecutor::blob(int bigSize, const std::string& blobPlaceholder) +{ + std::string lastName("lastname"); + std::string firstName("firstname"); + std::string address("Address"); + + CLOB img("0123456789", 10); + int count = 0; + try { session() << format("INSERT INTO Person VALUES (?,?,?,%s)", blobPlaceholder), + use(lastName), use(firstName), use(address), use(img), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 1); + + CLOB res; + assertTrue (res.size() == 0); + try { session() << "SELECT Image FROM Person", into(res), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (res == img); + + CLOB big; + std::vector v(bigSize, 'x'); + big.assignRaw(&v[0], v.size()); + + assertTrue (big.size() == bigSize); + + try { session() << "DELETE FROM Person", now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try + { + session() << format("INSERT INTO Person VALUES (?,?,?,%s)", blobPlaceholder), + use(lastName), use(firstName), use(address), use(big), now; + } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + // sometimes throws (intentionally, caught in caller) + session() << "SELECT Image FROM Person", into(res), now; + // when it doesn't throw, this must be true + assertTrue (res == big); +} + + +void SQLExecutor::blobStmt() +{ + std::string lastName("lastname"); + std::string firstName("firstname"); + std::string address("Address"); + CLOB blob("0123456789", 10); + + int count = 0; + Statement ins = (session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(blob)); + ins.execute(); + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 1); + + CLOB res; + poco_assert (res.size() == 0); + Statement stmt = (session() << "SELECT Image FROM Person", into(res)); + try { stmt.execute(); } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + poco_assert (res == blob); +} + + +void SQLExecutor::recordSet() +{ + std::string lastName("lastname"); + std::string firstName("firstname"); + std::string address("Address"); + DateTime born(1965, 6, 18, 5, 35, 1); + DateTime born2(1991, 6, 18, 14, 35, 1); + + try + { + { + Statement stmt = (session() << "SELECT COUNT(*) AS row_count FROM Person", now); + RecordSet rset(stmt); + assertTrue (rset.rowCount() == 1); + assertTrue (rset["row_count"].convert() == 0); + } + + { + Statement stmt = (session() << + "INSERT INTO Person VALUES (?,?,?,?)", + use(lastName), use(firstName), use(address), use(born), now); + RecordSet rset(stmt); + assertTrue (rset.rowCount() == 0); + assertTrue (rset.affectedRowCount() == 1); + } + + { + Statement stmt = (session() << "SELECT COUNT(*) AS row_count FROM Person", now); + RecordSet rset(stmt); + assertTrue (rset.rowCount() == 1); + assertTrue (rset["row_count"].convert() == 1); + } + + { + Statement stmt = (session() << "SELECT Born FROM Person", now); + RecordSet rset(stmt); + assertTrue (rset.rowCount() == 1); + assertTrue (rset["Born"].convert() == born); + } + + { + Statement stmt = (session() << + "DELETE FROM Person WHERE born = ?", use(born), now); + RecordSet rset(stmt); + assertTrue (rset.rowCount() == 0); + assertTrue (rset.affectedRowCount() == 1); + } + + { + Statement stmt = (session() << + "INSERT INTO Person VALUES (?,?,?,?)", + use(lastName), use(firstName), use(address), use(born), now); + RecordSet rset(stmt); + assertTrue (rset.rowCount() == 0); + assertTrue (rset.affectedRowCount() == 1); + } + + { + Statement stmt = (session() << + "INSERT INTO Person VALUES (?,?,?,?)", + use(lastName), use(firstName), use(address), use(born2), now); + RecordSet rset(stmt); + assertTrue (rset.rowCount() == 0); + assertTrue (rset.affectedRowCount() == 1); + } + + { + Statement stmt = (session() << "SELECT COUNT(*) AS row_count FROM Person", now); + RecordSet rset(stmt); + assertTrue (rset.rowCount() == 1); + assertTrue (rset["row_count"].convert() == 2); + } + + { + Statement stmt = (session() << "SELECT Born FROM Person ORDER BY Born DESC", now); + RecordSet rset(stmt); + assertTrue (rset.rowCount() == 2); + assertTrue (rset["Born"].convert() == born2); + rset.moveNext(); + assertTrue (rset["Born"].convert() == born); + rset.moveFirst(); + assertTrue (rset["Born"].convert() == born2); + rset.moveLast(); + assertTrue (rset["Born"].convert() == born); + } + + { + Statement stmt = (session() << "DELETE FROM Person", now); + RecordSet rset(stmt); + assertTrue (rset.rowCount() == 0); + assertTrue (rset.affectedRowCount() == 2); + } + } catch (ConnectionFailedException& ce){ std::cout << ce.displayText() << std::endl; fail (__func__, __LINE__, __FILE__); } + +} + + +void SQLExecutor::dateTime() +{ + std::string lastName("lastname"); + std::string firstName("firstname"); + std::string address("Address"); + + DateTime born(1965, 6, 18, 5, 35, 1); + int count = 0; + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(born), now; } catch (ConnectionFailedException& ce){ std::cout << ce.displayText() << std::endl; fail (__func__, __LINE__, __FILE__); } + + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } catch (ConnectionFailedException& ce){ std::cout << ce.displayText() << std::endl; fail (__func__, __LINE__, __FILE__); } + + assertTrue (count == 1); + + DateTime res; + try { session() << "SELECT Born FROM Person", into(res), now; } catch (ConnectionFailedException& ce){ std::cout << ce.displayText() << std::endl; fail (__func__, __LINE__, __FILE__); } + + assertTrue (res == born); + + Statement stmt = (session() << "SELECT Born FROM Person", now); + RecordSet rset(stmt); + + res = rset["Born"].convert(); + assertTrue (res == born); +} + + +void SQLExecutor::date() +{ + std::string lastName("lastname"); + std::string firstName("firstname"); + std::string address("Address"); + + Date bornDate(1965, 6, 18); + int count = 0; + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", + use(lastName), + use(firstName), + use(address), + use(bornDate), + now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 1); + + Date d; + Time t; + try { session() << "SELECT BornDate FROM Person", into(d), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (d == bornDate); + + Statement stmt = (session() << "SELECT BornDate FROM Person", now); + RecordSet rset(stmt); + + DateTime dt1 = rset["BornDate"].convert(); + + Date d2(dt1); + assertTrue (d2 == bornDate); +} + + +void SQLExecutor::time() +{ + std::string lastName("lastname"); + std::string firstName("firstname"); + std::string address("Address"); + + Time bornTime (5, 35, 1); + int count = 0; + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", + use(lastName), + use(firstName), + use(address), + use(bornTime), + now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 1); + + Date d; + Time t; + try { session() << "SELECT BornTime FROM Person", into(t), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (t == bornTime); + + Statement stmt = (session() << "SELECT BornTime FROM Person", now); + RecordSet rset(stmt); + + DateTime dt2 = rset["BornTime"].convert(); + Time t2(dt2); + assertTrue (t2 == bornTime); +} + + +void SQLExecutor::tuples() +{ + typedef Tuple TupleType; + TupleType t(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19); + + try { session() << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", use(t), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + TupleType ret(-10,-11,-12,-13,-14,-15,-16,-17,-18,-19); + assertTrue (ret != t); + try { session() << "SELECT * FROM Tuples", into(ret), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (ret == t); +} + +void SQLExecutor::tupleVector() +{ + typedef Tuple TupleType; + TupleType t(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19); + Tuple + t10(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29); + TupleType t100(100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119); + std::vector v; + v.push_back(t); + v.push_back(t10); + v.push_back(t100); + + try { session() << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", use(v), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int count = 0; + try { session() << "SELECT COUNT(*) FROM Tuples", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (v.size() == count); + + std::vector > ret; + try { session() << "SELECT * FROM Tuples", into(ret), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (ret == v); +} + + +void SQLExecutor::internalExtraction() +{ + std::vector > v; + v.push_back(Tuple(1, 1.5f, "3")); + v.push_back(Tuple(2, 2.5f, "4")); + v.push_back(Tuple(3, 3.5f, "5")); + v.push_back(Tuple(4, 4.5f, "6")); + + try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try + { + Statement stmt = (session() << "SELECT * FROM Vectors", now); + RecordSet rset(stmt); + + assertTrue (3 == rset.columnCount()); + assertTrue (4 == rset.rowCount()); + + int curVal = 3; + do + { + assertTrue (rset["str0"] == curVal); + ++curVal; + } while (rset.moveNext()); + + rset.moveFirst(); + assertTrue (rset["str0"] == "3"); + rset.moveLast(); + assertTrue (rset["str0"] == "6"); + + RecordSet rset2(rset); + assertTrue (3 == rset2.columnCount()); + assertTrue (4 == rset2.rowCount()); + + int i = rset.value(0,0); + assertTrue (1 == i); + + std::string s = rset.value(0,0).convert(); + assertTrue ("1" == s); + + int a = rset.value(0,2); + assertTrue (3 == a); + + try + { + double d = rset.value(1,1); + assertTrue (2.5 == d); + } + catch (BadCastException&) + { + float f = rset.value(1,1); + assertTrue (2.5 == f); + } + + try + { + s = rset.value(2, 2); + } + catch (BadCastException&) + { + UTF16String us = rset.value(2, 2); + Poco::UnicodeConverter::convert(us, s); + } + assertTrue ("5" == s); + + i = rset.value("str0", 2); + assertTrue (5 == i); + + const Column >& col = rset.column >(0); + Column >::Iterator it = col.begin(); + Column >::Iterator end = col.end(); + for (int i = 1; it != end; ++it, ++i) + assertTrue (*it == i); + + rset = (session() << "SELECT COUNT(*) AS cnt FROM Vectors", now); + + //various results for COUNT(*) are received from different drivers + try + { + //this is what most drivers will return + int i = rset.value(0,0); + assertTrue (4 == i); + } + catch(BadCastException&) + { + try + { + //this is for Oracle + double i = rset.value(0,0); + assertTrue (4 == int(i)); + } + catch(BadCastException&) + { + //this is for PostgreSQL + Poco::Int64 big = rset.value(0,0); + assertTrue (4 == big); + } + } + + s = rset.value("cnt", 0).convert(); + assertTrue ("4" == s); + + try { rset.column >(100); fail ("must fail"); } + catch (RangeException&) { } + + try { rset.value(0,0); fail ("must fail"); } + catch (BadCastException&) { } + + stmt = (session() << "DELETE FROM Vectors", now); + rset = stmt; + + try { rset.column >(0); fail ("must fail"); } + catch (RangeException&) { } + } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + +} + + +void SQLExecutor::filter(const std::string& query, const std::string& intFldName) +{ + std::vector > v; + v.push_back(Tuple(1, 1.5f, "3")); + v.push_back(Tuple(2, 2.5f, "4")); + v.push_back(Tuple(3, 3.5f, "5")); + v.push_back(Tuple(4, 4.5f, "6")); + + try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try + { + Statement stmt = (session() << query, now); + RecordSet rset(stmt); + assertTrue (rset.totalRowCount() == 4); + RowFilter::Ptr pRF = new RowFilter(&rset); + assertTrue (pRF->isEmpty()); + pRF->add(intFldName, RowFilter::VALUE_EQUAL, 1); + assertTrue (!pRF->isEmpty()); + + Var da; + try + { + da = rset.value(0, 1); + fail ("must fail"); + } catch (InvalidAccessException&) + { + da = rset.value(0, 1, false); + assertTrue (2 == da); + da = rset.value(0, 0); + assertTrue (1 == da); + } + + assertTrue (rset.rowCount() == 1); + assertTrue (rset.moveFirst()); + assertTrue (1 == rset[intFldName]); + assertTrue (!rset.moveNext()); + pRF->add("flt0", RowFilter::VALUE_LESS_THAN_OR_EQUAL, 3.5f); + assertTrue (rset.rowCount() == 3); + assertTrue (rset.moveNext()); + assertTrue (2.5 == rset["flt0"]); + assertTrue (rset.moveNext()); + assertTrue (3.5 == rset["flt0"]); + assertTrue (!rset.moveNext()); + pRF->add("str0", RowFilter::VALUE_EQUAL, 6); + assertTrue (rset.rowCount() == 4); + assertTrue (rset.moveLast()); + assertTrue ("6" == rset["str0"]); + pRF->remove("flt0"); + assertTrue (rset.rowCount() == 2); + assertTrue (rset.moveFirst()); + assertTrue ("3" == rset["str0"]); + assertTrue (rset.moveNext()); + assertTrue ("6" == rset["str0"]); + pRF->remove(intFldName); + pRF->remove("str0"); + assertTrue (pRF->isEmpty()); + pRF->add("str0", "!=", 3); + assertTrue (rset.rowCount() == 3); + + RowFilter::Ptr pRF1 = new RowFilter(pRF, RowFilter::OP_AND); + pRF1->add(intFldName, "==", 2); + assertTrue (rset.rowCount() == 1); + pRF1->add(intFldName, "<", 2); + assertTrue (rset.rowCount() == 1); + pRF1->add(intFldName, ">", 3); + assertTrue (rset.rowCount() == 2); + pRF->removeFilter(pRF1); + pRF->remove("str0"); + assertTrue (pRF->isEmpty()); + assertTrue (rset.rowCount() == 4); + } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + +} + + +void SQLExecutor::internalBulkExtraction() +{ + int size = 100; + std::vector lastName(size); + std::vector firstName(size); + std::vector address(size); + std::vector age(size); + + for (int i = 0; i < size; ++i) + { + lastName[i] = "LN" + NumberFormatter::format(i); + firstName[i] = "FN" + NumberFormatter::format(i); + address[i] = "Addr" + NumberFormatter::format(i); + age[i] = i; + } + + try + { + session() << "INSERT INTO Person VALUES (?,?,?,?)", + use(lastName, bulk), + use(firstName, bulk), + use(address, bulk), + use(age, bulk), + now; + } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try + { + Statement stmt = (session() << "SELECT * FROM Person", bulk(size), now); + RecordSet rset(stmt); + assertTrue (size == rset.rowCount()); + assertTrue ("LN0" == rset["LastName"]); + assertTrue (0 == rset["Age"]); + rset.moveNext(); + assertTrue ("LN1" == rset["LastName"]); + assertTrue (1 == rset["Age"]); + rset.moveLast(); + assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]); + assertTrue (size - 1 == rset["Age"]); + } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try + { + Statement stmt = (session() << "SELECT * FROM Person", limit(size), bulk, now); + RecordSet rset(stmt); + assertTrue (size == rset.rowCount()); + assertTrue ("LN0" == rset["LastName"]); + assertTrue (0 == rset["Age"]); + rset.moveLast(); + assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]); + assertTrue (size - 1 == rset["Age"]); + } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } +} + + +void SQLExecutor::internalBulkExtractionUTF16() +{ + int size = 100; + std::vector lastName(size); + std::vector firstName(size); + std::vector address(size); + std::vector age(size); + + for (int i = 0; i < size; ++i) + { + lastName[i] = Poco::UnicodeConverter::to("LN" + NumberFormatter::format(i)); + firstName[i] = Poco::UnicodeConverter::to("FN" + NumberFormatter::format(i)); + address[i] = Poco::UnicodeConverter::to("Addr" + NumberFormatter::format(i)); + age[i] = i; + } + + try + { + session() << "INSERT INTO Person VALUES (?,?,?,?)", + use(lastName, bulk), + use(firstName, bulk), + use(address, bulk), + use(age, bulk), + now; + } catch (ConnectionFailedException& ce){ std::cout << ce.displayText() << std::endl; fail (__func__, __LINE__, __FILE__); } + + try + { + Statement stmt = (session() << "SELECT * FROM Person", bulk(size), now); + RecordSet rset(stmt); + assertTrue (size == rset.rowCount()); + assertTrue (Poco::UnicodeConverter::to("LN0") == rset["LastName"]); + assertTrue (0 == rset["Age"]); + rset.moveNext(); + assertTrue (Poco::UnicodeConverter::to("LN1") == rset["LastName"]); + assertTrue (1 == rset["Age"]); + rset.moveLast(); + assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]); + assertTrue (size - 1 == rset["Age"]); + } catch (ConnectionFailedException& ce){ std::cout << ce.displayText() << std::endl; fail (__func__, __LINE__, __FILE__); } + + try + { + Statement stmt = (session() << "SELECT * FROM Person", limit(size), bulk, now); + RecordSet rset(stmt); + assertTrue (size == rset.rowCount()); + assertTrue ("LN0" == rset["LastName"]); + assertTrue (0 == rset["Age"]); + rset.moveLast(); + assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]); + assertTrue (size - 1 == rset["Age"]); + } catch (ConnectionFailedException& ce){ std::cout << ce.displayText() << std::endl; fail (__func__, __LINE__, __FILE__); } + +} + + +void SQLExecutor::internalStorageType() +{ + std::vector manips; + manips.push_back(list); + manips.push_back(deque); + manips.push_back(vector); + + std::vector > v; + v.push_back(Tuple(1, 1.5f, "3")); + v.push_back(Tuple(2, 2.5f, "4")); + v.push_back(Tuple(3, 3.5f, "5")); + v.push_back(Tuple(4, 4.5f, "6")); + + try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try + { + std::vector::iterator it = manips.begin(); + std::vector::iterator end = manips.end(); + + for (; it != end; ++it) + { + Statement stmt = (session() << "SELECT * FROM Vectors", *it, now); + RecordSet rset(stmt); + + assertTrue (3 == rset.columnCount()); + assertTrue (4 == rset.rowCount()); + + int curVal = 3; + do + { + assertTrue (rset["str0"] == curVal); + ++curVal; + } while (rset.moveNext()); + + rset.moveFirst(); + assertTrue (rset["str0"] == "3"); + rset.moveLast(); + assertTrue (rset["str0"] == "6"); + + try + { + stmt = (session() << "SELECT * FROM Vectors", now, *it); + fail ("must fail"); + } + catch(InvalidAccessException&){} + + try + { + stmt = (session() << "SELECT * FROM Vectors", into(v), now, *it); + fail ("must fail"); + } + catch(InvalidAccessException&){} + + try + { + stmt = (session() << "SELECT * FROM Vectors", into(v), *it, now); + fail ("must fail"); + } + catch(InvalidAccessException&){} + } + } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + +} + + +void SQLExecutor::nulls() +{ + try { session() << "INSERT INTO NullTest (i,r,v) VALUES (?,?,?)", use(null), use(null), use(null), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + RecordSet rs(session(), "SELECT * FROM NullTest"); + assertTrue (1 == rs.rowCount()); + rs.moveFirst(); + assertTrue (rs.isNull("i")); + assertTrue (rs["i"] != 0); + assertTrue (rs.isNull("r")); + assertTrue (rs.isNull("v")); + assertTrue (rs["v"] != ""); + assertTrue (rs.nvl("i") == 0); + assertTrue (rs.nvl("i", -1) == -1); + assertTrue (rs.nvl("r") == double()); + assertTrue (rs.nvl("r", -1.5) == -1.5); + assertTrue (rs.nvl("v") == ""); + assertTrue (rs.nvl("v", "123") == "123"); + try { session() << "DELETE FROM NullTest", now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + int i = 1; + double f = 1.5; + std::string s = "123"; + + try { session() << "INSERT INTO NullTest (i, r, v) VALUES (?,?,?)", use(i), use(f), use(s), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + rs = (session() << "SELECT * FROM NullTest", now); + assertTrue (1 == rs.rowCount()); + rs.moveFirst(); + assertTrue (!rs.isNull("i")); + assertTrue (rs["i"] == 1); + assertTrue (!rs.isNull("v")); + assertTrue (!rs.isNull("r")); + assertTrue (rs["v"] == "123"); + assertTrue (rs.nvl("i") == 1); + assertTrue (rs.nvl("i", -1) == 1); + assertTrue (rs.nvl("r") == 1.5); + assertTrue (rs.nvl("r", -1.5) == 1.5); + assertTrue (rs.nvl("v") == "123"); + assertTrue (rs.nvl("v", "456") == "123"); + try { session() << "UPDATE NullTest SET v = ? WHERE i = ?", use(null), use(i), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + i = 2; + f = 3.4; + try { session() << "INSERT INTO NullTest (i, r, v) VALUES (?,?,?)", use(i), use(null), use(null), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + rs = (session() << "SELECT i, r, v FROM NullTest ORDER BY i ASC", now); + assertTrue (2 == rs.rowCount()); + rs.moveFirst(); + assertTrue (!rs.isNull("i")); + assertTrue (rs["i"] == 1); + assertTrue (!rs.isNull("r")); + assertTrue (rs.isNull("v")); + assertTrue (rs["v"] != ""); + + assertTrue (rs.moveNext()); + assertTrue (!rs.isNull("i")); + assertTrue (rs["i"] == 2); + assertTrue (rs.isNull("r")); + assertTrue (rs.isNull("v")); + assertTrue (rs["v"] != ""); + + try { session() << "DELETE FROM NullTest", now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + try { session() << "INSERT INTO NullTest (v) VALUES (?)", bind(""), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + bool esin = session().getFeature("emptyStringIsNull"); + session().setFeature("emptyStringIsNull", true); + + try + { + session().setFeature("forceEmptyString", true); + fail ("must fail"); + } catch (InvalidAccessException&) { } + + bool fes = session().getFeature("forceEmptyString"); + session().setFeature("forceEmptyString", false); + + RecordSet rs1(session(), "SELECT v FROM NullTest"); + assertTrue (1 == rs1.rowCount()); + rs1.moveFirst(); + assertTrue (rs1.isNull("v")); + assertTrue (!(rs["v"] == "")); + + session().setFeature("emptyStringIsNull", false); + session().setFeature("forceEmptyString", true); + RecordSet rs2(session(), "SELECT v FROM NullTest"); + assertTrue (1 == rs2.rowCount()); + rs2.moveFirst(); + assertTrue (!rs2.isNull("v")); + assertTrue ((rs2["v"] == "")); + + try + { + session().setFeature("emptyStringIsNull", true); + fail ("must fail"); + } catch (InvalidAccessException&) { } + + session().setFeature("emptyStringIsNull", esin); + session().setFeature("forceEmptyString", fes); +} + + +void SQLExecutor::rowIterator() +{ + std::vector > v; + v.push_back(Tuple(1, 1.5f, "3")); + v.push_back(Tuple(2, 2.5f, "4")); + v.push_back(Tuple(3, 3.5f, "5")); + v.push_back(Tuple(4, 4.5f, "6")); + + try { session() << "DELETE FROM Vectors", now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + RecordSet rset0(session(), "SELECT * FROM Vectors"); + assertTrue (rset0.begin() == rset0.end()); + + try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + RecordSet rset(session(), "SELECT * FROM Vectors"); + + std::ostringstream osLoop; + RecordSet::Iterator it = rset.begin(); + RecordSet::Iterator end = rset.end(); + for (int i = 1; it != end; ++it, ++i) + { + assertTrue (it->get(0) == i); + osLoop << *it; + } + assertTrue (!osLoop.str().empty()); + + std::ostringstream osCopy; + std::copy(rset.begin(), rset.end(), std::ostream_iterator(osCopy)); + assertTrue (osLoop.str() == osCopy.str()); + + RowFilter::Ptr pRF = new RowFilter(&rset); + assertTrue (pRF->isEmpty()); + pRF->add("str0", RowFilter::VALUE_EQUAL, "3"); + assertTrue (!pRF->isEmpty()); + it = rset.begin(); + end = rset.end(); + for (int i = 1; it != end; ++it, ++i) + { + assertTrue (it->get(0) == i); + assertTrue (1 == i); + } +} + + +void SQLExecutor::stdVectorBool() +{ + bool b = false; + try { session() << "INSERT INTO BoolTest VALUES (?)", use(b), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + b = true; + session() << "SELECT * FROM BoolTest", into(b), now; + assertTrue (false == b); + session() << "DELETE FROM BoolTest", now; + + b = true; + try { session() << "INSERT INTO BoolTest VALUES (?)", use(b), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + b = false; + session() << "SELECT * FROM BoolTest", into(b), now; + assertTrue (true == b); + session() << "DELETE FROM BoolTest", now; + + std::vector v; + v.push_back(true); + v.push_back(false); + v.push_back(false); + v.push_back(true); + + try { session() << "INSERT INTO BoolTest VALUES (?)", use(v), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + v.clear(); + session() << "SELECT * FROM BoolTest", into(v), now; + + assertTrue (4 == v.size()); + std::vector::iterator it = v.begin(); + std::vector::iterator end = v.end(); + int t = 0; + for (; it != end; ++it) + t += *it ? 1 : 0; + assertTrue (2 == t); + + try { session() << "SELECT * FROM BoolTest WHERE b = ?", out(v), now; fail("must fail"); } catch (BindingException&) { } + + try { session() << "SELECT * FROM BoolTest WHERE b = ?", io(v), now; fail("must fail"); } catch (BindingException&) { } + + RecordSet rset(session(), "SELECT * FROM BoolTest"); + + t = 0; + for (int i = 0; i < 4; ++i) + t += rset.value(0, i) ? 1 : 0; + assertTrue (2 == t); +} + + +void SQLExecutor::asynchronous(int rowCount) +{ + Session tmp = session(); + + std::vector data(rowCount); + Statement stmt = (tmp << "INSERT INTO Strings VALUES(?)", use(data)); + Statement::Result result = stmt.executeAsync(); + assertTrue (!stmt.isAsync()); + result.wait(); + + Statement stmt1 = (tmp << "SELECT * FROM Strings", into(data), async, now); + assertTrue (stmt1.isAsync()); + assertTrue (stmt1.wait() == rowCount); + + // +++ if this part of the test case fails, increase the rowCount until achieved + // that first execute is still executing when the second one is called + stmt1.execute(); + try { + stmt1.execute(); + fail ("execute() must fail"); + } catch (InvalidAccessException&) + { + stmt1.wait(); + stmt1.execute(); + stmt1.wait(); + } + // --- + + stmt = tmp << "SELECT * FROM Strings", into(data), async, now; + assertTrue (stmt.isAsync()); + stmt.wait(); + assertTrue (stmt.execute() == 0); + + // +++ if this part of the test case fails, increase the rowCount until achieved + // that first execute is still executing when the second one is called + try { + result = stmt.executeAsync(); + fail ("executeAsync() must fail"); + } catch (InvalidAccessException&) + { + assertTrue (stmt.isAsync()); + stmt.wait(); + result = stmt.executeAsync(); + } + // --- + + assertTrue (stmt.wait() == rowCount); + assertTrue (result.data() == rowCount); + stmt.setAsync(false); + assertTrue (!stmt.isAsync()); + assertTrue (stmt.execute() == rowCount); + + stmt = tmp << "SELECT * FROM Strings", into(data), sync, now; + assertTrue (!stmt.isAsync()); + assertTrue (stmt.wait() == 0); + assertTrue (stmt.execute() == rowCount); + result = stmt.executeAsync(); + assertTrue (!stmt.isAsync()); + result.wait(); + assertTrue (result.data() == rowCount); + + assertTrue (0 == rowCount % 10); + int step = (int) (rowCount/10); + data.clear(); + Statement stmt2 = (tmp << "SELECT * FROM Strings", into(data), async, limit(step)); + assertTrue (data.size() == 0); + assertTrue (!stmt2.done()); + std::size_t rows = 0; + + for (int i = 0; !stmt2.done(); i += step) + { + stmt2.execute(); + rows = stmt2.wait(); + assertTrue (step == rows); + assertTrue (step + i == data.size()); + } + assertTrue (stmt2.done()); + assertTrue (rowCount == data.size()); + + stmt2 = tmp << "SELECT * FROM Strings", reset; + assertTrue (!stmt2.isAsync()); + assertTrue ("deque" == stmt2.getStorage()); + assertTrue (stmt2.execute() == rowCount); +} + + +void SQLExecutor::any() +{ + Any i = 42; + Any f = 42.5; + std::string ss("42"); + Any s = ss; + + Session tmp = session(); + + tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now; + + int count = 0; + tmp << "SELECT COUNT(*) FROM Anys", into(count), now; + assertTrue (1 == count); + + i = 0; + f = 0.0; + s = std::string(""); + tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now; + assertTrue (AnyCast(i) == 42); + assertTrue (AnyCast(f) == 42.5); + assertTrue (AnyCast(s) == "42"); +} + + +void SQLExecutor::dynamicAny() +{ + Var i = 42; + Var f = 42.5; + Var s = "42"; + + Session tmp = session(); + tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now; + + int count = 0; + tmp << "SELECT COUNT(*) FROM Anys", into(count), now; + assertTrue (1 == count); + + i = 0; + f = 0.0; + s = std::string(""); + tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now; + assertTrue (42 == i); + assertTrue (42.5 == f); + assertTrue ("42" == s); +} + + +void SQLExecutor::multipleResults(const std::string& sql) +{ + typedef Tuple Person; + std::vector people; + people.push_back(Person("Simpson", "Homer", "Springfield", 42)); + people.push_back(Person("Simpson", "Marge", "Springfield", 38)); + people.push_back(Person("Simpson", "Bart", "Springfield", 10)); + people.push_back(Person("Simpson", "Lisa", "Springfield", 8)); + people.push_back(Person("Simpson", "Maggie", "Springfield", 3)); + session() << "INSERT INTO Person VALUES (?, ?, ?, ?)", use(people), now; + + Person pHomer; + int aHomer = 42, aLisa = 8; + Poco::UInt32 aBart = 0; + + Poco::UInt32 pos1 = 1; + int pos2 = 2; + std::vector people2; + Statement stmt(session()); + stmt << sql, into(pHomer, from(0)), use(aHomer) + , into(aBart, pos1) + , into(people2, from(pos2)), use(aLisa), use(aHomer); + + assertTrue (4 == stmt.execute()); + assertTrue (Person("Simpson", "Homer", "Springfield", 42) == pHomer); + assertTrue (10 == aBart); + assertTrue (2 == people2.size()); + assertTrue (Person("Simpson", "Lisa", "Springfield", 8) == people2[0]); + assertTrue (Person("Simpson", "Homer", "Springfield", 42) == people2[1]); +} + + +void SQLExecutor::sqlChannel(const std::string& connector, const std::string& connect) +{ + try + { + AutoPtr pChannel = new SQLChannel(connector, connect, "TestSQLChannel"); + Stopwatch sw; sw.start(); + while (!pChannel->isRunning()) + { + Thread::sleep(10); + if (sw.elapsedSeconds() > 3) + fail ("SQLExecutor::sqlLogger(): SQLChannel timed out"); + } + + pChannel->setProperty("bulk", "true"); + pChannel->setProperty("keep", "2 seconds"); + + Message msgInf("InformationSource", "a Informational async message", Message::PRIO_INFORMATION); + pChannel->log(msgInf); + while (pChannel->logged() != 1) Thread::sleep(10); + + Message msgWarn("WarningSource", "b Warning async message", Message::PRIO_WARNING); + pChannel->log(msgWarn); + while (pChannel->logged() != 2) Thread::sleep(10); + + Message msgInfS("InformationSource", "c Informational sync message", Message::PRIO_INFORMATION); + pChannel->log(msgInfS); + while (pChannel->logged() != 3) Thread::sleep(10); + Message msgWarnS("WarningSource", "d Warning sync message", Message::PRIO_WARNING); + pChannel->log(msgWarnS); + while (pChannel->logged() != 4) Thread::sleep(10); + + RecordSet rs(session(), "SELECT * FROM T_POCO_LOG ORDER by Text"); + size_t rc = rs.rowCount(); + assertTrue (4 == rc); + assertTrue ("InformationSource" == rs["Source"]); + assertTrue ("a Informational async message" == rs["Text"]); + rs.moveNext(); + assertTrue ("WarningSource" == rs["Source"]); + assertTrue ("b Warning async message" == rs["Text"]); + rs.moveNext(); + assertTrue ("InformationSource" == rs["Source"]); + assertTrue ("c Informational sync message" == rs["Text"]); + rs.moveNext(); + assertTrue ("WarningSource" == rs["Source"]); + assertTrue ("d Warning sync message" == rs["Text"]); + + Thread::sleep(3000); // give it time to archive + + Message msgInfA("InformationSource", "e Informational sync message", Message::PRIO_INFORMATION); + pChannel->log(msgInfA); + while (pChannel->logged() != 5) Thread::sleep(10); + Message msgWarnA("WarningSource", "f Warning sync message", Message::PRIO_WARNING); + pChannel->log(msgWarnA); + while (pChannel->logged() != 6) Thread::sleep(10); + + RecordSet rs1(session(), "SELECT * FROM T_POCO_LOG_ARCHIVE"); + assertTrue (4 == rs1.rowCount()); + + pChannel->setProperty("keep", ""); + assertTrue ("forever" == pChannel->getProperty("keep")); + RecordSet rs2(session(), "SELECT * FROM T_POCO_LOG ORDER by Text"); + assertTrue (2 == rs2.rowCount()); + assertTrue ("InformationSource" == rs2["Source"]); + assertTrue ("e Informational sync message" == rs2["Text"]); + rs2.moveNext(); + assertTrue ("WarningSource" == rs2["Source"]); + assertTrue ("f Warning sync message" == rs2["Text"]); + } catch(DataException& ce){ std::cout << ce.displayText() << std::endl; fail ("sqlChannel()"); } +} + + +void SQLExecutor::sqlLogger(const std::string& connector, const std::string& connect) +{ + try + { + Logger& root = Logger::root(); + SQLChannel* pSQLChannel = new SQLChannel(connector, connect, "TestSQLChannel"); + Stopwatch sw; sw.start(); + while (!pSQLChannel->isRunning()) + { + Thread::sleep(10); + if (sw.elapsedSeconds() > 3) + fail ("SQLExecutor::sqlLogger(): SQLChannel timed out"); + } + + root.setChannel(pSQLChannel); + root.setLevel(Message::PRIO_INFORMATION); + + root.information("a Informational message"); + root.warning("b Warning message"); + root.debug("Debug message"); + + while (pSQLChannel->logged() != 2) Thread::sleep(100); + RecordSet rs(session(), "SELECT * FROM T_POCO_LOG ORDER by Text"); + assertTrue (2 == rs.rowCount()); + assertTrue ("TestSQLChannel" == rs["Source"]); + assertTrue ("a Informational message" == rs["Text"]); + rs.moveNext(); + assertTrue ("TestSQLChannel" == rs["Source"]); + assertTrue ("b Warning message" == rs["Text"]); + } catch(DataException& ce){ std::cout << ce.displayText() << std::endl; fail ("sqlLogger()"); } +} + + +void SQLExecutor::setTransactionIsolation(Session& session, Poco::UInt32 ti) +{ + if (session.hasTransactionIsolation(ti)) + { + try + { + Transaction t(session, false); + t.setIsolation(ti); + + assertTrue (ti == t.getIsolation()); + assertTrue (t.isIsolation(ti)); + + assertTrue (ti == session.getTransactionIsolation()); + assertTrue (session.isTransactionIsolation(ti)); + } + catch(Poco::Exception& e){ std::cout << __func__ << ':' << e.displayText() << std::endl;} + } + else + { + std::cerr << '[' << name() << ']' << " Warning, transaction isolation not supported: "; + switch (ti) + { + case Session::TRANSACTION_READ_COMMITTED: + std::cerr << "READ COMMITTED"; break; + case Session::TRANSACTION_READ_UNCOMMITTED: + std::cerr << "READ UNCOMMITTED"; break; + case Session::TRANSACTION_REPEATABLE_READ: + std::cerr << "REPEATABLE READ"; break; + case Session::TRANSACTION_SERIALIZABLE: + std::cerr << "SERIALIZABLE"; break; + default: + std::cerr << "UNKNOWN"; break; + } + std::cerr << std::endl; + } +} + + +void SQLExecutor::autoCommit() +{ + 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() +{ + 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); + + setTransactionIsolation(session(), ti); +} + + +void SQLExecutor::sessionTransaction(const std::string& connector, const std::string& connect) +{ + if (!session().canTransact()) + { + std::cout << "Session not capable of transactions." << std::endl; + return; + } + + bool autoCommit = session().getFeature("autoCommit"); + + Session local(connector, connect); + + 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); + assertTrue (session().getFeature("autoCommit")); + assertTrue (!session().isTransaction()); + + session().begin(); + assertTrue (session().isTransaction()); + assertTrue (!session().getFeature("autoCommit")); + + // changing 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) { } + // make sure nothing was changed ... + assertTrue (!session().getFeature("autoCommit")); + // but setting it to its current state is allowed (no-op) + session().setFeature("autoCommit", false); + assertTrue (!session().getFeature("autoCommit")); + + 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); + + session() << "SELECT COUNT(*) FROM Person", into(count), now; + assertTrue (2 == count); + assertTrue (session().isTransaction()); + session().rollback(); + assertTrue (!session().isTransaction()); + + stmt.wait(); + assertTrue (0 == locCount); + stmt.reset(session()); + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (0 == count); + assertTrue (!session().isTransaction()); + + session().begin(); + session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; + assertTrue (session().isTransaction()); + + stmt = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now); + + session().commit(); + assertTrue (!session().isTransaction()); + + stmt.wait(); + assertTrue (2 == locCount); + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (2 == count); + // end autoCommit = true + + // restore the original transaction state + session().setFeature("autoCommit", autoCommit); +} + + +void SQLExecutor::sessionTransactionNoAutoCommit(const std::string& connector, 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::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); +#ifndef POCO_DATA_NO_SQL_PARSER + assertTrue (local.isTransaction()); + + // autocommit is invalid for session in transaction ... + try + { + local.setFeature("autoCommit", true); + fail ("must fail on autocommit setting during transaction", __LINE__); + } catch(const Poco::InvalidAccessException& e) { } + + // but setting it to its current state is allowed (no-op) + local.setFeature("autoCommit", false); + + assertTrue (!session().isTransaction()); +#else + session().commit(); +#endif // POCO_DATA_NO_SQL_PARSER + 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); +#ifndef POCO_DATA_NO_SQL_PARSER + assertTrue (local.isTransaction()); + assertTrue (!session().isTransaction()); +#else + session().commit(); +#endif + + 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); +#ifndef POCO_DATA_NO_SQL_PARSER + session().commit(); + local.commit(); +#endif + session().setFeature("autoCommit", autoCommit); +} + + +void SQLExecutor::transaction(const std::string& connector, const std::string& connect) +{ + if (!session().canTransact()) + { + std::cout << "Session not transaction-capable." << std::endl; + return; + } + + 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); + else if (local.hasTransactionIsolation(Session::TRANSACTION_READ_COMMITTED)) + setTransactionIsolation(local, Session::TRANSACTION_READ_COMMITTED); + + 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); + assertTrue (!session().isTransaction()); + session().setFeature("autoCommit", false); + assertTrue (!session().isTransaction()); + session().setTransactionIsolation(Session::TRANSACTION_READ_COMMITTED); + + { + Transaction trans(session()); + assertTrue (trans.isActive()); + assertTrue (session().isTransaction()); + + session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; + + assertTrue (session().isTransaction()); + assertTrue (trans.isActive()); + + session() << "SELECT COUNT(*) FROM Person", into(count), now; + assertTrue (2 == count); + assertTrue (session().isTransaction()); + assertTrue (trans.isActive()); + } + assertTrue (!session().isTransaction()); + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (0 == count); + assertTrue (!session().isTransaction()); + session().commit(); + + { + Transaction trans(session()); + session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; + + Statement stmt1 = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now); + + assertTrue (session().isTransaction()); + assertTrue (trans.isActive()); + trans.commit(); + assertTrue (!session().isTransaction()); + assertTrue (!trans.isActive()); + + stmt1.wait(); + assertTrue (2 == locCount); + } + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (2 == count); + + session() << "DELETE FROM Person", now; + + Statement stmt1 = (local << "SELECT count(*) FROM Person", into(locCount), async, now); + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (0 == count); + try + { + stmt1.wait(5000); + if (local.getTransactionIsolation() == Session::TRANSACTION_READ_UNCOMMITTED) + assertTrue (0 == locCount); + } catch (TimeoutException&) + { std::cerr << '[' << name() << ']' << " Warning: async query timed out." << std::endl; } + session().commit(); + // repeat for those that don't support uncommitted read isolation + if (local.getTransactionIsolation() == Session::TRANSACTION_READ_COMMITTED) + { + stmt1.wait(); + local << "SELECT count(*) FROM Person", into(locCount), now; + assertTrue (0 == locCount); + } + + std::string sql1 = format("INSERT INTO Person VALUES ('%s','%s','%s',%d)", lastNames[0], firstNames[0], addresses[0], ages[0]); + std::string sql2 = format("INSERT INTO Person VALUES ('%s','%s','%s',%d)", lastNames[1], firstNames[1], addresses[1], ages[1]); + std::vector sql; + sql.push_back(sql1); + sql.push_back(sql2); + + Transaction trans(session()); + + trans.execute(sql1, false); + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (1 == count); + trans.execute(sql2, false); + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (2 == count); + + Statement stmt2 = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now); + + trans.rollback(); + + stmt2.wait(); + assertTrue (0 == locCount); + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (0 == count); + + trans.execute(sql); + + Statement stmt3 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now); + assertTrue (2 == locCount); + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (2 == count); + session().commit(); + + // restore the original transaction state + session().setFeature("autoCommit", autoCommit); + setTransactionIsolation(session(), ti); +} + + +struct TestCommitTransactor +{ + void operator () (Session& session) const + { + session << "INSERT INTO Person VALUES ('lastName','firstName','address',10)", now; + } +}; + + +struct TestRollbackTransactor +{ + void operator () (Session& session) const + { + session << "INSERT INTO Person VALUES ('lastName','firstName','address',10)", now; + throw Poco::Exception("test"); + } +}; + + +void 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); + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (1 == count); + + session() << "DELETE FROM Person", now; session().commit(); + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (0 == count); + + try + { + TestRollbackTransactor rt; + Transaction t(session(), rt); + fail ("must fail"); + } catch (Poco::Exception&) { } + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (0 == count); + + try + { + TestRollbackTransactor rt; + Transaction t(session()); + t.transact(rt); + fail ("must fail"); + } catch (Poco::Exception&) { } + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (0 == count); + + try + { + TestRollbackTransactor rt; + Transaction t(session(), false); + t.transact(rt); + fail ("must fail"); + } catch (Poco::Exception&) { } + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (0 == count); + + try + { + TestRollbackTransactor rt; + Transaction t(session(), true); + t.transact(rt); + fail ("must fail"); + } catch (Poco::Exception&) { } + + session() << "SELECT count(*) FROM Person", into(count), now; + assertTrue (0 == count); + session().commit(); + + // restore the original transaction state + session().setFeature("autoCommit", autoCommit); + setTransactionIsolation(session(), ti); +} + + +void SQLExecutor::nullable() +{ + try { session() << "INSERT INTO NullableTest VALUES(NULL, NULL, NULL, NULL)", now; } catch(DataException& ce){ std::cout << ce.displayText() << std::endl; fail ("nullable()", __LINE__, __FILE__); } + + Nullable i = 1; + Nullable f = 1.5; + Nullable s = std::string("abc"); + Nullable d = DateTime(); + + assertTrue (!i.isNull()); + assertTrue (!f.isNull()); + assertTrue (!s.isNull()); + assertTrue (!d.isNull()); + + session() << "SELECT EmptyString, EmptyInteger, EmptyFloat, EmptyDateTime FROM NullableTest", into(s), into(i), into(f), into(d), now; + + assertTrue (i.isNull()); + assertTrue (f.isNull()); + assertTrue (s.isNull()); + assertTrue (d.isNull()); + + RecordSet rs(session(), "SELECT * FROM NullableTest"); + + rs.moveFirst(); + assertTrue (rs.isNull("EmptyString")); + assertTrue (rs.isNull("EmptyInteger")); + assertTrue (rs.isNull("EmptyFloat")); + assertTrue (rs.isNull("EmptyDateTime")); + + Var di = 1; + Var df = 1.5; + Var ds = "abc"; + Var dd = DateTime(); + + assertTrue (!di.isEmpty()); + assertTrue (!df.isEmpty()); + assertTrue (!ds.isEmpty()); + assertTrue (!dd.isEmpty()); + + Statement stmt = (session() << "SELECT EmptyString, EmptyInteger, EmptyFloat, EmptyDateTime FROM NullableTest", into(ds), into(di), into(df), into(dd), now); + + assertTrue (di.isEmpty()); + assertTrue (df.isEmpty()); + assertTrue (ds.isEmpty()); + assertTrue (dd.isEmpty()); +} + + +void SQLExecutor::reconnect() +{ + std::string lastName = "lastName"; + std::string firstName("firstName"); + std::string address("Address"); + int age = 133132; + int count = 0; + std::string result; + + try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + + count = 0; + try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == 1); + + assertTrue (session().isConnected()); + session().close(); + assertTrue (!session().isConnected()); + try + { + session() << "SELECT LastName FROM Person", into(result), now; + fail ("must fail"); + } catch(NotConnectedException&){ } + assertTrue (!session().isConnected()); + + session().open(); + assertTrue (session().isConnected()); + try { session() << "SELECT Age FROM Person", into(count), now; } + catch(DataException& ce) + { + std::cout << ce.displayText() << std::endl; + fail (__func__, __LINE__, __FILE__); + } + + assertTrue (count == age); + assertTrue (session().isConnected()); +} + + +void SQLExecutor::unicode(const std::string& dbConnString) +{ + const unsigned char supp[] = { 0x41, 0x42, 0xf0, 0x90, 0x82, 0xa4, 0xf0, 0xaf, 0xa6, 0xa0, 0xf0, 0xaf, 0xa8, 0x9d, 0x00 }; + std::string text((const char*) supp); + + UTF16String wtext; + Poco::UnicodeConverter::convert(text, wtext); + session() << "INSERT INTO UnicodeTable VALUES (?)", use(wtext), now; + wtext.clear(); + text.clear(); + session() << "SELECT str FROM UnicodeTable", into(wtext), now; + Poco::UnicodeConverter::convert(wtext, text); + assertTrue (text == std::string((const char*)supp)); +} + + +void SQLExecutor::encoding(const std::string& dbConnString) +{ + try + { + const unsigned char latinChars[] = { 'g', 252, 'n', 't', 'e', 'r', 0 }; + const unsigned char utf8Chars[] = { 'g', 195, 188, 'n', 't', 'e', 'r', 0 }; + std::string latinText((const char*)latinChars); + std::string utf8TextIn((const char*)utf8Chars); + + session(true) << "INSERT INTO Latin1Table VALUES (?)", use(utf8TextIn), now; + + std::string latinTextOut; + session() << "SELECT str FROM Latin1Table", into(latinTextOut), now; + assertTrue(latinText == latinTextOut); + + std::string utf8TextOut; + session(true) << "SELECT str FROM Latin1Table", into(utf8TextOut), now; + assertTrue(utf8TextIn == utf8TextOut); + + const unsigned char latinChars2[] = { 'G', 220, 'N', 'T', 'E', 'R', 0 }; + const unsigned char utf8Chars2[] = { 'G', 195, 156, 'N', 'T', 'E', 'R', 0 }; + std::string latinText2 = (const char*)latinChars2; + std::string utf8TextIn2 = (const char*)utf8Chars2; + + session(true) << "INSERT INTO Latin1Table VALUES (?)", use(utf8TextIn2), now; + + std::vector textOutVec; + session() << "SELECT str FROM Latin1Table", into(textOutVec), now; + assertTrue(textOutVec.size() == 2); + assertTrue(textOutVec[0] == latinText); + assertTrue(textOutVec[1] == latinText2); + + textOutVec.clear(); + session(true) << "SELECT str FROM Latin1Table", into(textOutVec), now; + assertTrue(textOutVec.size() == 2); + assertTrue(textOutVec[0] == utf8TextIn); + assertTrue(textOutVec[1] == utf8TextIn2); + } + catch (Poco::Exception& ex) + { + std::cerr << ex.displayText() << std::endl; + throw; + } + catch (std::exception& ex) + { + std::cerr << ex.what() << std::endl; + throw; + } +} + +} } } // Poco::Data::Test