diff --git a/Data/Data_VS90.vcproj b/Data/Data_VS90.vcproj index 81d72bf92..87919dcd6 100644 --- a/Data/Data_VS90.vcproj +++ b/Data/Data_VS90.vcproj @@ -450,10 +450,6 @@ RelativePath=".\include\Poco\Data\MetaColumn.h" > - - diff --git a/Data/MySQL/include/Poco/Data/MySQL/Connector.h b/Data/MySQL/include/Poco/Data/MySQL/Connector.h index 61d714507..160cf6f80 100644 --- a/Data/MySQL/include/Poco/Data/MySQL/Connector.h +++ b/Data/MySQL/include/Poco/Data/MySQL/Connector.h @@ -1,80 +1,80 @@ -// -// Connector.h -// -// $Id: //poco/1.4/Data/MySQL/include/Poco/Data/MySQL/Connector.h#1 $ -// -// Library: Data -// Package: MySQL -// Module: Connector -// -// Definition of the Connector class. -// -// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// Permission is hereby granted, free of charge, to any person or organization -// obtaining a copy of the software and accompanying documentation covered by -// this license (the "Software") to use, reproduce, display, distribute, -// execute, and transmit the Software, and to prepare derivative works of the -// Software, and to permit third-parties to whom the Software is furnished to -// do so, all subject to the following: -// -// The copyright notices in the Software and this entire statement, including -// the above license grant, this restriction and the following disclaimer, -// must be included in all copies of the Software, in whole or in part, and -// all derivative works of the Software, unless such copies or derivative -// works are solely in the form of machine-executable object code generated by -// a source language processor. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// - - -#ifndef Data_MySQL_Connector_INCLUDED -#define Data_MySQL_Connector_INCLUDED - -#include "MySQL.h" -#include "Poco/Data/Connector.h" - -namespace Poco { -namespace Data { -namespace MySQL { - -class MySQL_API Connector: public Poco::Data::Connector - /// Connector instantiates MySQL SessionImpl objects. -{ -public: - - static std::string KEY; - - Connector(); - /// Creates the Connector. - - virtual ~Connector(); - /// Destroys the Connector. - - virtual const std::string& name() const; - /// Returns the name associated with this connector. - +// +// Connector.h +// +// $Id: //poco/1.4/Data/MySQL/include/Poco/Data/MySQL/Connector.h#1 $ +// +// Library: Data +// Package: MySQL +// Module: Connector +// +// Definition of the Connector class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Data_MySQL_Connector_INCLUDED +#define Data_MySQL_Connector_INCLUDED + +#include "MySQL.h" +#include "Poco/Data/Connector.h" + +namespace Poco { +namespace Data { +namespace MySQL { + +class MySQL_API Connector: public Poco::Data::Connector + /// Connector instantiates MySQL SessionImpl objects. +{ +public: + + static std::string KEY; + + Connector(); + /// Creates the Connector. + + virtual ~Connector(); + /// Destroys the Connector. + + virtual const std::string& name() const; + /// Returns the name associated with this connector. + virtual Poco::AutoPtr createSession(const std::string& connectionString, - std::size_t timeout = Poco::Data::SessionImpl::LOGIN_TIMEOUT_DEFAULT); - /// Creates a MySQL SessionImpl object and initializes it with the given connectionString. - - static void registerConnector(); - /// Registers the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory - - static void unregisterConnector(); - /// Unregisters the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory -}; - - -} } } // namespace Poco::Data::MySQL - - -#endif // Data_MySQL_Connector_INCLUDED + std::size_t timeout = Poco::Data::SessionImpl::LOGIN_TIMEOUT_DEFAULT); + /// Creates a MySQL SessionImpl object and initializes it with the given connectionString. + + static void registerConnector(); + /// Registers the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory + + static void unregisterConnector(); + /// Unregisters the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory +}; + + +} } } // namespace Poco::Data::MySQL + + +#endif // Data_MySQL_Connector_INCLUDED diff --git a/Data/MySQL/include/Poco/Data/MySQL/MySQL.h b/Data/MySQL/include/Poco/Data/MySQL/MySQL.h index 21882febd..757448e28 100644 --- a/Data/MySQL/include/Poco/Data/MySQL/MySQL.h +++ b/Data/MySQL/include/Poco/Data/MySQL/MySQL.h @@ -52,7 +52,7 @@ // defined with this macro as being exported. // #if defined(_WIN32) && defined(POCO_DLL) - #if defined(MYSQL_EXPORTS) + #if defined(MySQL_EXPORTS) #define MySQL_API __declspec(dllexport) #else #define MySQL_API __declspec(dllimport) @@ -69,7 +69,7 @@ // Automatically link Data library. // #if defined(_MSC_VER) - #if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(MYSQL_EXPORTS) + #if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(MySQL_EXPORTS) #if defined(POCO_DLL) #if defined(_DEBUG) #pragma comment(lib, "PocoDataMySQLd.lib") diff --git a/Data/MySQL/include/Poco/Data/MySQL/MySQLStatementImpl.h b/Data/MySQL/include/Poco/Data/MySQL/MySQLStatementImpl.h index 3a2b9207a..aeba37eaa 100644 --- a/Data/MySQL/include/Poco/Data/MySQL/MySQLStatementImpl.h +++ b/Data/MySQL/include/Poco/Data/MySQL/MySQLStatementImpl.h @@ -81,7 +81,7 @@ protected: virtual bool hasNext(); /// Returns true if a call to next() will return data. - virtual std::size_t next(); + virtual std::size_t next(); /// Retrieves the next row from the resultset. /// Will throw, if the resultset is empty. diff --git a/Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h b/Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h index 33d6ff541..34220a870 100644 --- a/Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h +++ b/Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h @@ -54,37 +54,37 @@ class SessionHandle public: explicit SessionHandle(MYSQL* mysql); - /// Creates session handle + /// Creates session handle ~SessionHandle(); - /// Destroy handle, close connection + /// Destroy handle, close connection void init(MYSQL* mysql = 0); /// Initializes the handle iff not initialized. void options(mysql_option opt); - /// Set connection options + /// Set connection options void options(mysql_option opt, bool b); - /// Set connection options + /// Set connection options void options(mysql_option opt, unsigned int i); - /// Set connection options + /// Set connection options void connect(const char* host, const char* user, const char* password, const char* db, unsigned int port); - /// Connect to server + /// Connect to server void close(); - /// Close connection + /// Close connection void startTransaction(); - /// Start transaction + /// Start transaction void commit(); - /// Commit transaction + /// Commit transaction void rollback(); - /// Rollback trabsaction + /// Rollback trabsaction operator MYSQL* (); @@ -94,7 +94,7 @@ private: SessionHandle& operator=(const SessionHandle&); private: - + MYSQL* _pHandle; }; diff --git a/Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h b/Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h index e83acc7f3..1e890db1a 100644 --- a/Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h +++ b/Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h @@ -138,8 +138,8 @@ public: Poco::Any getInsertId(const std::string&); /// Get insert id - SessionHandle& handle(); - // Get handle + SessionHandle& handle(); + // Get handle const std::string& connectorName(); /// Returns the name of the connector. @@ -204,7 +204,7 @@ inline Poco::Any SessionImpl::getInsertId(const std::string&) inline SessionHandle& SessionImpl::handle() { - return _handle; + return _handle; } diff --git a/Data/MySQL/src/Connector.cpp b/Data/MySQL/src/Connector.cpp index 67351c114..40fd7f00f 100644 --- a/Data/MySQL/src/Connector.cpp +++ b/Data/MySQL/src/Connector.cpp @@ -1,93 +1,93 @@ -// -// MySQLException.cpp -// -// $Id: //poco/1.4/Data/MySQL/src/Connector.cpp#1 $ -// -// Library: Data -// Package: MySQL -// Module: Connector -// -// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// Permission is hereby granted, free of charge, to any person or organization -// obtaining a copy of the software and accompanying documentation covered by -// this license (the "Software") to use, reproduce, display, distribute, -// execute, and transmit the Software, and to prepare derivative works of the -// Software, and to permit third-parties to whom the Software is furnished to -// do so, all subject to the following: -// -// The copyright notices in the Software and this entire statement, including -// the above license grant, this restriction and the following disclaimer, -// must be included in all copies of the Software, in whole or in part, and -// all derivative works of the Software, unless such copies or derivative -// works are solely in the form of machine-executable object code generated by -// a source language processor. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// - - -#include "Poco/Data/MySQL/Connector.h" -#include "Poco/Data/MySQL/SessionImpl.h" -#include "Poco/Data/SessionFactory.h" -#include "Poco/Exception.h" - -#include - - -namespace Poco { -namespace Data { -namespace MySQL { - - -std::string Connector::KEY("mysql"); - - -Connector::Connector() -{ -} - - -Connector::~Connector() -{ -} - -const std::string& Connector::name() const -{ - return KEY; -} - +// +// MySQLException.cpp +// +// $Id: //poco/1.4/Data/MySQL/src/Connector.cpp#1 $ +// +// Library: Data +// Package: MySQL +// Module: Connector +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Data/MySQL/Connector.h" +#include "Poco/Data/MySQL/SessionImpl.h" +#include "Poco/Data/SessionFactory.h" +#include "Poco/Exception.h" + +#include + + +namespace Poco { +namespace Data { +namespace MySQL { + + +std::string Connector::KEY("mysql"); + + +Connector::Connector() +{ +} + + +Connector::~Connector() +{ +} + +const std::string& Connector::name() const +{ + return KEY; +} + Poco::AutoPtr Connector::createSession(const std::string& connectionString, - std::size_t timeout) -{ - return Poco::AutoPtr(new SessionImpl(connectionString, timeout)); -} - - -void Connector::registerConnector() -{ - if (mysql_library_init(0, 0, 0) != 0) - { - throw Exception("mysql_library_init error"); - } - - Poco::Data::SessionFactory::instance().add(new Connector()); -} - - -void Connector::unregisterConnector() -{ - Poco::Data::SessionFactory::instance().remove(KEY); - mysql_library_end(); -} - - -} } } // namespace Poco::Data::MySQL - + std::size_t timeout) +{ + return Poco::AutoPtr(new SessionImpl(connectionString, timeout)); +} + + +void Connector::registerConnector() +{ + if (mysql_library_init(0, 0, 0) != 0) + { + throw Exception("mysql_library_init error"); + } + + Poco::Data::SessionFactory::instance().add(new Connector()); +} + + +void Connector::unregisterConnector() +{ + Poco::Data::SessionFactory::instance().remove(KEY); + mysql_library_end(); +} + + +} } } // namespace Poco::Data::MySQL + diff --git a/Data/MySQL/src/MySQLStatementImpl.cpp b/Data/MySQL/src/MySQLStatementImpl.cpp index 656468a77..7cbe712e1 100644 --- a/Data/MySQL/src/MySQLStatementImpl.cpp +++ b/Data/MySQL/src/MySQLStatementImpl.cpp @@ -41,10 +41,10 @@ namespace Data { namespace MySQL { -MySQLStatementImpl::MySQLStatementImpl(SessionImpl& h) - : Poco::Data::StatementImpl(h), - _stmt(h.handle()), - _extractor(_stmt, _metadata), +MySQLStatementImpl::MySQLStatementImpl(SessionImpl& h) : + Poco::Data::StatementImpl(h), + _stmt(h.handle()), + _extractor(_stmt, _metadata), _hasNext(NEXT_DONTKNOW) { } @@ -63,7 +63,7 @@ std::size_t MySQLStatementImpl::columnsReturned() const std::size_t MySQLStatementImpl::affectedRowCount() const { - return 0; + return 0; } @@ -116,7 +116,7 @@ std::size_t MySQLStatementImpl::next() } _hasNext = NEXT_DONTKNOW; - return 1; + return 1; } @@ -136,7 +136,7 @@ bool MySQLStatementImpl::canCompile() const return (_stmt.state() < StatementExecutor::STMT_COMPILED); } - + void MySQLStatementImpl::compileImpl() { _metadata.reset(); @@ -147,7 +147,7 @@ void MySQLStatementImpl::compileImpl() _stmt.bindResult(_metadata.row()); } - + void MySQLStatementImpl::bindImpl() { Poco::Data::AbstractBindingVec& binds = bindings(); @@ -165,13 +165,13 @@ void MySQLStatementImpl::bindImpl() _hasNext = NEXT_DONTKNOW; } - + AbstractExtractor& MySQLStatementImpl::extractor() { return _extractor; } - + AbstractBinder& MySQLStatementImpl::binder() { return _binder; diff --git a/Data/MySQL/src/SessionHandle.cpp b/Data/MySQL/src/SessionHandle.cpp index 66952ed3e..b4d700d38 100644 --- a/Data/MySQL/src/SessionHandle.cpp +++ b/Data/MySQL/src/SessionHandle.cpp @@ -96,7 +96,7 @@ void SessionHandle::options(mysql_option opt, unsigned int i) void SessionHandle::connect(const char* host, const char* user, const char* password, const char* db, unsigned int port) { if (!mysql_real_connect(_pHandle, host, user, password, db, port, 0, 0)) - throw ConnectionFailedException("mysql_real_connect error"); + throw ConnectionFailedException(mysql_error(_pHandle)); } @@ -112,21 +112,21 @@ void SessionHandle::close() void SessionHandle::startTransaction() { - if (mysql_autocommit(_pHandle, false) != 0) + if (mysql_autocommit(_pHandle, false) != 0) throw TransactionException("Start transaction failed.", _pHandle); } void SessionHandle::commit() { - if (mysql_commit(_pHandle) != 0) + if (mysql_commit(_pHandle) != 0) throw TransactionException("Commit failed.", _pHandle); } void SessionHandle::rollback() { - if (mysql_rollback(_pHandle) != 0) + if (mysql_rollback(_pHandle) != 0) throw TransactionException("Rollback failed.", _pHandle); } diff --git a/Data/MySQL/src/SessionImpl.cpp b/Data/MySQL/src/SessionImpl.cpp index 591b050a9..85b06d86f 100644 --- a/Data/MySQL/src/SessionImpl.cpp +++ b/Data/MySQL/src/SessionImpl.cpp @@ -184,21 +184,21 @@ void SessionImpl::begin() if (_inTransaction) throw Poco::InvalidAccessException("Already in transaction."); - _handle.startTransaction(); + _handle.startTransaction(); _inTransaction = true; } void SessionImpl::commit() { - _handle.commit(); + _handle.commit(); _inTransaction = false; } void SessionImpl::rollback() { - _handle.rollback(); + _handle.rollback(); _inTransaction = false; } diff --git a/Data/MySQL/src/StatementExecutor.cpp b/Data/MySQL/src/StatementExecutor.cpp index 573ddfeda..a3c294240 100644 --- a/Data/MySQL/src/StatementExecutor.cpp +++ b/Data/MySQL/src/StatementExecutor.cpp @@ -67,17 +67,17 @@ int StatementExecutor::state() const void StatementExecutor::prepare(const std::string& query) { - if (_state >= STMT_COMPILED) - { - _state = STMT_COMPILED; - return; - } + if (_state >= STMT_COMPILED) + { + _state = STMT_COMPILED; + return; + } - if (mysql_stmt_prepare(_pHandle, query.c_str(), static_cast(query.length())) != 0) - throw StatementException("mysql_stmt_prepare error", _pHandle, query); + if (mysql_stmt_prepare(_pHandle, query.c_str(), static_cast(query.length())) != 0) + throw StatementException("mysql_stmt_prepare error", _pHandle, query); - _query = query; - _state = STMT_COMPILED; + _query = query; + _state = STMT_COMPILED; } diff --git a/Data/MySQL/testsuite/src/MySQLTest.cpp b/Data/MySQL/testsuite/src/MySQLTest.cpp index eb4d02188..c9b7b7420 100644 --- a/Data/MySQL/testsuite/src/MySQLTest.cpp +++ b/Data/MySQL/testsuite/src/MySQLTest.cpp @@ -42,7 +42,7 @@ #include "Poco/Data/StatementImpl.h" #include "Poco/Data/MySQL/Connector.h" #include "Poco/Data/MySQL/MySQLException.h" -#include "Poco/Data/Nullable.h" +#include "Poco/Nullable.h" #include "Poco/Data/DataException.h" #include @@ -53,7 +53,7 @@ using Poco::Data::MySQL::StatementException; using Poco::format; using Poco::NotFoundException; using Poco::Int32; -using Poco::Data::Nullable; +using Poco::Nullable; using Poco::Tuple; using Poco::NamedTuple; @@ -63,14 +63,15 @@ Poco::SharedPtr MySQLTest::_pExecutor = 0; // // Parameters for barebone-test #define MYSQL_USER "root" -#define MYSQL_PWD "" +#define MYSQL_PWD "poco" #define MYSQL_HOST "localhost" #define MYSQL_PORT 3306 #define MYSQL_DB "test" // -// Connection string to POCO -std::string MySQLTest::_dbConnString = "user=" MYSQL_USER +// Connection string +std::string MySQLTest::_dbConnString = "host=" MYSQL_HOST + ";user=" MYSQL_USER ";password=" MYSQL_PWD ";db=" MYSQL_DB ";compress=true;auto-reconnect=true"; @@ -79,7 +80,7 @@ std::string MySQLTest::_dbConnString = "user=" MYSQL_USER MySQLTest::MySQLTest(const std::string& name): CppUnit::TestCase(name) { - MySQL::Connector::registerConnector(); + MySQL::Connector::registerConnector(); } @@ -605,27 +606,27 @@ void MySQLTest::testTupleWithNullable() typedef Poco::Tuple, Nullable > Info; Info info(0, std::string("Address"), 10); - *_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(info), now; + *_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(info), now; info.set<0>(info.get<0>()++); info.set<1>(null); - *_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(info), now; + *_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(info), now; info.set<0>(info.get<0>()++); info.set<1>(std::string("Address!")); info.set<2>(null); - *_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(info), now; + *_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(info), now; std::vector infos; infos.push_back(Info(10, std::string("A"), 0)); infos.push_back(Info(11, null, 12)); infos.push_back(Info(12, std::string("B"), null)); - *_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(infos), now; + *_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(infos), now; std::vector result; - *_pSession << "SELECT Id, Address, Age FROM NullableStringTest", into(result), now; + *_pSession << "SELECT Id, Address, Age FROM NullableStringTest", into(result), now; assert(result[0].get<1>() == std::string("Address")); assert(result[0].get<2>() == 10); @@ -650,10 +651,10 @@ void MySQLTest::testTupleWithNullable() void MySQLTest::dropTable(const std::string& tableName) { - - try { *_pSession << format("DROP TABLE IF EXISTS %s", tableName), now; } - catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("dropTable()"); } - catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("dropTable()"); } + + try { *_pSession << format("DROP TABLE IF EXISTS %s", tableName), now; } + catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("dropTable()"); } + catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("dropTable()"); } } @@ -718,7 +719,7 @@ void MySQLTest::recreateNullableIntTable() { dropTable("NullableIntTest"); try { - *_pSession << "CREATE TABLE NullableIntTest (Id INTEGER(10), Value INTEGER(10))", now; + *_pSession << "CREATE TABLE NullableIntTest (Id INTEGER(10), Value INTEGER(10))", now; } catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateNullableIntTable()"); } catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateNullableIntTable()"); } @@ -729,7 +730,7 @@ void MySQLTest::recreateNullableStringTable() { dropTable("NullableStringTest"); try { - *_pSession << "CREATE TABLE NullableStringTest (Id INTEGER(10), Address VARCHAR(30), Age INTEGER(10))", now; + *_pSession << "CREATE TABLE NullableStringTest (Id INTEGER(10), Address VARCHAR(30), Age INTEGER(10))", now; } catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateNullableStringTable()"); } catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateNullableStringTable()"); } @@ -765,7 +766,7 @@ CppUnit::Test* MySQLTest::suite() { _pSession = new Session(MySQL::Connector::KEY, _dbConnString); } - catch (ConnectionFailedException& ex) + catch (ConnectionFailedException& ex) { std::cout << ex.displayText() << std::endl; return 0; @@ -775,55 +776,55 @@ CppUnit::Test* MySQLTest::suite() _pExecutor = new SQLExecutor("MySQL SQL Executor", _pSession); - CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MySQLTest"); + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MySQLTest"); - CppUnit_addTest(pSuite, MySQLTest, testBareboneMySQL); - CppUnit_addTest(pSuite, MySQLTest, testSimpleAccess); - CppUnit_addTest(pSuite, MySQLTest, testComplexType); - CppUnit_addTest(pSuite, MySQLTest, testSimpleAccessVector); - CppUnit_addTest(pSuite, MySQLTest, testComplexTypeVector); - CppUnit_addTest(pSuite, MySQLTest, testInsertVector); - CppUnit_addTest(pSuite, MySQLTest, testInsertEmptyVector); - CppUnit_addTest(pSuite, MySQLTest, testInsertSingleBulk); - CppUnit_addTest(pSuite, MySQLTest, testInsertSingleBulkVec); - CppUnit_addTest(pSuite, MySQLTest, testLimit); - CppUnit_addTest(pSuite, MySQLTest, testLimitOnce); - CppUnit_addTest(pSuite, MySQLTest, testLimitPrepare); - CppUnit_addTest(pSuite, MySQLTest, testLimitZero); - CppUnit_addTest(pSuite, MySQLTest, testPrepare); - CppUnit_addTest(pSuite, MySQLTest, testSetSimple); - CppUnit_addTest(pSuite, MySQLTest, testSetComplex); - CppUnit_addTest(pSuite, MySQLTest, testSetComplexUnique); - CppUnit_addTest(pSuite, MySQLTest, testMultiSetSimple); - CppUnit_addTest(pSuite, MySQLTest, testMultiSetComplex); - CppUnit_addTest(pSuite, MySQLTest, testMapComplex); - CppUnit_addTest(pSuite, MySQLTest, testMapComplexUnique); - CppUnit_addTest(pSuite, MySQLTest, testMultiMapComplex); - CppUnit_addTest(pSuite, MySQLTest, testSelectIntoSingle); - CppUnit_addTest(pSuite, MySQLTest, testSelectIntoSingleStep); - CppUnit_addTest(pSuite, MySQLTest, testSelectIntoSingleFail); - CppUnit_addTest(pSuite, MySQLTest, testLowerLimitOk); - CppUnit_addTest(pSuite, MySQLTest, testLowerLimitFail); - CppUnit_addTest(pSuite, MySQLTest, testCombinedLimits); - CppUnit_addTest(pSuite, MySQLTest, testCombinedIllegalLimits); - CppUnit_addTest(pSuite, MySQLTest, testRange); - CppUnit_addTest(pSuite, MySQLTest, testIllegalRange); - CppUnit_addTest(pSuite, MySQLTest, testSingleSelect); - CppUnit_addTest(pSuite, MySQLTest, testEmptyDB); - //CppUnit_addTest(pSuite, MySQLTest, testBLOB); - CppUnit_addTest(pSuite, MySQLTest, testBLOBStmt); - CppUnit_addTest(pSuite, MySQLTest, testFloat); - CppUnit_addTest(pSuite, MySQLTest, testDouble); - CppUnit_addTest(pSuite, MySQLTest, testTuple); - CppUnit_addTest(pSuite, MySQLTest, testTupleVector); - CppUnit_addTest(pSuite, MySQLTest, testInternalExtraction); - CppUnit_addTest(pSuite, MySQLTest, testNull); - CppUnit_addTest(pSuite, MySQLTest, testNullableInt); - CppUnit_addTest(pSuite, MySQLTest, testNullableString); - CppUnit_addTest(pSuite, MySQLTest, testTupleWithNullable); + CppUnit_addTest(pSuite, MySQLTest, testBareboneMySQL); + CppUnit_addTest(pSuite, MySQLTest, testSimpleAccess); + CppUnit_addTest(pSuite, MySQLTest, testComplexType); + CppUnit_addTest(pSuite, MySQLTest, testSimpleAccessVector); + CppUnit_addTest(pSuite, MySQLTest, testComplexTypeVector); + CppUnit_addTest(pSuite, MySQLTest, testInsertVector); + CppUnit_addTest(pSuite, MySQLTest, testInsertEmptyVector); + CppUnit_addTest(pSuite, MySQLTest, testInsertSingleBulk); + CppUnit_addTest(pSuite, MySQLTest, testInsertSingleBulkVec); + CppUnit_addTest(pSuite, MySQLTest, testLimit); + CppUnit_addTest(pSuite, MySQLTest, testLimitOnce); + CppUnit_addTest(pSuite, MySQLTest, testLimitPrepare); + CppUnit_addTest(pSuite, MySQLTest, testLimitZero); + CppUnit_addTest(pSuite, MySQLTest, testPrepare); + CppUnit_addTest(pSuite, MySQLTest, testSetSimple); + CppUnit_addTest(pSuite, MySQLTest, testSetComplex); + CppUnit_addTest(pSuite, MySQLTest, testSetComplexUnique); + CppUnit_addTest(pSuite, MySQLTest, testMultiSetSimple); + CppUnit_addTest(pSuite, MySQLTest, testMultiSetComplex); + CppUnit_addTest(pSuite, MySQLTest, testMapComplex); + CppUnit_addTest(pSuite, MySQLTest, testMapComplexUnique); + CppUnit_addTest(pSuite, MySQLTest, testMultiMapComplex); + CppUnit_addTest(pSuite, MySQLTest, testSelectIntoSingle); + CppUnit_addTest(pSuite, MySQLTest, testSelectIntoSingleStep); + CppUnit_addTest(pSuite, MySQLTest, testSelectIntoSingleFail); + CppUnit_addTest(pSuite, MySQLTest, testLowerLimitOk); + CppUnit_addTest(pSuite, MySQLTest, testLowerLimitFail); + CppUnit_addTest(pSuite, MySQLTest, testCombinedLimits); + CppUnit_addTest(pSuite, MySQLTest, testCombinedIllegalLimits); + CppUnit_addTest(pSuite, MySQLTest, testRange); + CppUnit_addTest(pSuite, MySQLTest, testIllegalRange); + CppUnit_addTest(pSuite, MySQLTest, testSingleSelect); + CppUnit_addTest(pSuite, MySQLTest, testEmptyDB); + //CppUnit_addTest(pSuite, MySQLTest, testBLOB); + CppUnit_addTest(pSuite, MySQLTest, testBLOBStmt); + CppUnit_addTest(pSuite, MySQLTest, testFloat); + CppUnit_addTest(pSuite, MySQLTest, testDouble); + CppUnit_addTest(pSuite, MySQLTest, testTuple); + CppUnit_addTest(pSuite, MySQLTest, testTupleVector); + CppUnit_addTest(pSuite, MySQLTest, testInternalExtraction); + CppUnit_addTest(pSuite, MySQLTest, testNull); + CppUnit_addTest(pSuite, MySQLTest, testNullableInt); + CppUnit_addTest(pSuite, MySQLTest, testNullableString); + CppUnit_addTest(pSuite, MySQLTest, testTupleWithNullable); CppUnit_addTest(pSuite, MySQLTest, testSessionTransaction); CppUnit_addTest(pSuite, MySQLTest, testTransaction); CppUnit_addTest(pSuite, MySQLTest, testReconnect); - return pSuite; + return pSuite; } diff --git a/Data/MySQL/testsuite/src/SQLExecutor.h b/Data/MySQL/testsuite/src/SQLExecutor.h index 19e902619..cccf8e8a0 100644 --- a/Data/MySQL/testsuite/src/SQLExecutor.h +++ b/Data/MySQL/testsuite/src/SQLExecutor.h @@ -1,125 +1,125 @@ -// -// SQLExecutor.h -// -// $Id: //poco/1.4/Data/MySQL/testsuite/src/SQLExecutor.h#1 $ -// -// Definition of the SQLExecutor class. -// -// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// Permission is hereby granted, free of charge, to any person or organization -// obtaining a copy of the software and accompanying documentation covered by -// this license (the "Software") to use, reproduce, display, distribute, -// execute, and transmit the Software, and to prepare derivative works of the -// Software, and to permit third-parties to whom the Software is furnished to -// do so, all subject to the following: -// -// The copyright notices in the Software and this entire statement, including -// the above license grant, this restriction and the following disclaimer, -// must be included in all copies of the Software, in whole or in part, and -// all derivative works of the Software, unless such copies or derivative -// works are solely in the form of machine-executable object code generated by -// a source language processor. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// - - -#ifndef SQLExecutor_INCLUDED -#define SQLExecutor_INCLUDED - - -#include "Poco/Data/MySQL/MySQL.h" -#include "Poco/Data/Session.h" - -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); - ~SQLExecutor(); - - void bareboneMySQLTest(const char* host, const char* user, const char* pwd, const char* db, int port, const char* tableCreateString); - /// This function uses "bare bone" MySQL API calls (i.e. calls are not - /// "wrapped" in PocoData framework structures). - /// The purpose of the function is to verify that driver behaves - /// correctly. If this test passes, subsequent tests failures are likely ours. - - void simpleAccess(); - void complexType(); - void simpleAccessVector(); - void complexTypeVector(); - void insertVector(); - void insertEmptyVector(); - - void insertSingleBulk(); - void insertSingleBulkVec(); - - void limits(); - void limitOnce(); - void limitPrepare(); - void limitZero(); - void prepare(); - - 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); - void blobStmt(); - - void floats(); - void doubles(); - void tuples(); - void tupleVector(); - - void internalExtraction(); - void doNull(); - +// +// SQLExecutor.h +// +// $Id: //poco/1.4/Data/MySQL/testsuite/src/SQLExecutor.h#1 $ +// +// Definition of the SQLExecutor class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SQLExecutor_INCLUDED +#define SQLExecutor_INCLUDED + + +#include "Poco/Data/MySQL/MySQL.h" +#include "Poco/Data/Session.h" + +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); + ~SQLExecutor(); + + void bareboneMySQLTest(const char* host, const char* user, const char* pwd, const char* db, int port, const char* tableCreateString); + /// This function uses "bare bone" MySQL API calls (i.e. calls are not + /// "wrapped" in PocoData framework structures). + /// The purpose of the function is to verify that driver behaves + /// correctly. If this test passes, subsequent tests failures are likely ours. + + void simpleAccess(); + void complexType(); + void simpleAccessVector(); + void complexTypeVector(); + void insertVector(); + void insertEmptyVector(); + + void insertSingleBulk(); + void insertSingleBulkVec(); + + void limits(); + void limitOnce(); + void limitPrepare(); + void limitZero(); + void prepare(); + + 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); + void blobStmt(); + + void floats(); + void doubles(); + void tuples(); + void tupleVector(); + + void internalExtraction(); + void doNull(); + void sessionTransaction(const std::string& connect); - void transaction(const std::string& connect); - - void reconnect(); - -private: - void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti); - - Poco::Data::Session* _pSession; -}; - - -#endif // SQLExecutor_INCLUDED + void transaction(const std::string& connect); + + void reconnect(); + +private: + void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti); + + Poco::Data::Session* _pSession; +}; + + +#endif // SQLExecutor_INCLUDED diff --git a/Data/ODBC/include/Poco/Data/ODBC/Extractor.h b/Data/ODBC/include/Poco/Data/ODBC/Extractor.h index 2e2d833cc..4ecc7dd82 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Extractor.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Extractor.h @@ -51,7 +51,8 @@ #include "Poco/Data/Time.h" #include "Poco/DateTime.h" #include "Poco/Any.h" -#include "Poco/DynamicAny.h" +#include "Poco/Dynamic/Var.h" +#include "Poco/Nullable.h" #include "Poco/Exception.h" #include #ifdef POCO_OS_FAMILY_WINDOWS diff --git a/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp b/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp index 37d8004f9..fa9fbdeb3 100644 --- a/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp @@ -61,7 +61,7 @@ using Poco::NotFoundException; #ifdef POCO_OS_FAMILY_WINDOWS - #define MYSQL_ODBC_DRIVER "MySQL ODBC 3.51 Driver" + #define MYSQL_ODBC_DRIVER "MySQL ODBC 5.1 Driver" #else #define MYSQL_ODBC_DRIVER "MySQL" #endif @@ -69,7 +69,7 @@ using Poco::NotFoundException; #define MYSQL_SERVER POCO_ODBC_TEST_DATABASE_SERVER #define MYSQL_DB "test" #define MYSQL_UID "root" -#define MYSQL_PWD "mysql" +#define MYSQL_PWD "poco" ODBCTest::SessionPtr ODBCMySQLTest::_pSession; @@ -88,6 +88,7 @@ std::string ODBCMySQLTest::_connectString = "DRIVER=" MYSQL_ODBC_DRIVER ODBCMySQLTest::ODBCMySQLTest(const std::string& name): ODBCTest(name, _pSession, _pExecutor, _dsn, _uid, _pwd, _connectString) { + _pExecutor->execute("SET @@global.sql_mode= '';"); // disable strict mode } @@ -115,17 +116,27 @@ void ODBCMySQLTest::testBareboneODBC() /* MySQL supports batch statements as of 3.51.18 -http://bugs.mysql.com/bug.php?id=7445 +(http://bugs.mysql.com/bug.php?id=7445) +has different SQL syntax for it and behaves differently +compared to other DBMS systems in regards to SQLMoreResults. +So, we skip this test. tableCreateString = "CREATE TABLE Test " "(First VARCHAR(30)," "Second INTEGER," "Third FLOAT)"; - _pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL); - _pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND); - _pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL); - _pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND); + std::string MULTI_INSERT = "INSERT INTO Test VALUES " + "('1', 2, 3.5)," + "('2', 3, 4.5)," + "('3', 4, 5.5)," + "('4', 5, 6.5)," + "('5', 6, 7.5);"; + + _pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL, MULTI_INSERT); + _pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND, MULTI_INSERT); + _pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL, MULTI_INSERT); + _pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND, MULTI_INSERT); */ } diff --git a/Data/ODBC/testsuite/src/SQLExecutor.cpp b/Data/ODBC/testsuite/src/SQLExecutor.cpp index 32103ed7d..e59d2c8cb 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.cpp +++ b/Data/ODBC/testsuite/src/SQLExecutor.cpp @@ -62,6 +62,7 @@ #include "Poco/Data/ODBC/Connector.h" #include "Poco/Data/ODBC/Utility.h" #include "Poco/Data/ODBC/Diagnostics.h" +#include "Poco/Data/ODBC/Error.h" #include "Poco/Data/ODBC/Preparator.h" #include "Poco/Data/ODBC/ODBCException.h" #include "Poco/Data/ODBC/ODBCStatementImpl.h" @@ -92,7 +93,7 @@ using Poco::Data::ODBC::Preparator; using Poco::Data::ODBC::ConnectionException; using Poco::Data::ODBC::StatementException; using Poco::Data::ODBC::DataTruncatedException; -using Poco::Data::ODBC::StatementDiagnostics; +using Poco::Data::ODBC::StatementError; using Poco::format; using Poco::Tuple; using Poco::Nullable; @@ -112,6 +113,7 @@ using Poco::InvalidArgumentException; using Poco::NotImplementedException; using Poco::BadCastException; using Poco::RangeException; +using Poco::TimeoutException; struct Person @@ -948,6 +950,14 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString, } +void SQLExecutor::execute(const std::string& sql) +{ + try { session() << sql, now; } + catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (sql); } + catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (sql); } +} + + void SQLExecutor::simpleAccess() { std::string funct = "simpleAccess()"; @@ -2927,10 +2937,15 @@ void SQLExecutor::notNulls(const std::string& sqlState) fail ("must fail"); }catch (StatementException& se) { - //make sure we're failing for the right reason + //double check if we're failing for the right reason //default sqlState value is "23502"; some drivers report "HY???" codes if (se.diagnostics().fields().size()) - assert (sqlState == se.diagnostics().sqlState(0)); + { + std::string st = se.diagnostics().sqlState(0); + if (sqlState != st) + std::cerr << '[' << name() << ']' << " Warning: expected SQL state [" << sqlState << + "], received [" << se.diagnostics().sqlState(0) << "] instead." << std::endl; + } } } @@ -3431,21 +3446,21 @@ void SQLExecutor::setTransactionIsolation(Session& session, Poco::UInt32 ti) } else { - std::cout << "Transaction isolation not supported: "; + std::cerr << '[' << name() << ']' << " Warning, transaction isolation not supported: "; switch (ti) { case Session::TRANSACTION_READ_COMMITTED: - std::cout << "READ COMMITTED"; break; + std::cerr << "READ COMMITTED"; break; case Session::TRANSACTION_READ_UNCOMMITTED: - std::cout << "READ UNCOMMITTED"; break; + std::cerr << "READ UNCOMMITTED"; break; case Session::TRANSACTION_REPEATABLE_READ: - std::cout << "REPEATABLE READ"; break; + std::cerr << "REPEATABLE READ"; break; case Session::TRANSACTION_SERIALIZABLE: - std::cout << "SERIALIZABLE"; break; + std::cerr << "SERIALIZABLE"; break; default: - std::cout << "UNKNOWN"; break; + std::cerr << "UNKNOWN"; break; } - std::cout << std::endl; + std::cerr << std::endl; } } @@ -3552,7 +3567,10 @@ void SQLExecutor::transaction(const std::string& connect) local.setFeature("autoCommit", true); setTransactionIsolation(session(), Session::TRANSACTION_READ_COMMITTED); - setTransactionIsolation(local, 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::vector lastNames; @@ -3633,16 +3651,27 @@ void SQLExecutor::transaction(const std::string& connect) catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } - Statement stmt1 = (local << "SELECT COUNT(*) FROM PERSON", into(locCount), async, now); + Statement stmt1 = (local << "SELECT count(*) FROM PERSON", into(locCount), async, now); try { session() << "SELECT count(*) FROM PERSON", into(count), now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } assert (0 == count); + try + { + stmt1.wait(5000); + if (local.getTransactionIsolation() == Session::TRANSACTION_READ_UNCOMMITTED) + assert (0 == locCount); + } catch (TimeoutException&) + { std::cerr << '[' << name() << ']' << " Warning: async query timed out." << std::endl; } session().commit(); - - stmt1.wait(); - assert (0 == locCount); + // 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; + assert (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]); diff --git a/Data/ODBC/testsuite/src/SQLExecutor.h b/Data/ODBC/testsuite/src/SQLExecutor.h index f9e5288b6..ca162c9f2 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.h +++ b/Data/ODBC/testsuite/src/SQLExecutor.h @@ -112,6 +112,9 @@ public: SQLExecutor(const std::string& name, Poco::Data::Session* _pSession); ~SQLExecutor(); + void execute(const std::string& sql); + /// Execute a query. + void bareboneODBCTest(const std::string& dbConnString, const std::string& tableCreateString, DataBinding bindMode, @@ -125,8 +128,8 @@ public: SQLExecutor::DataExtraction extractMode, const std::string& insert = MULTI_INSERT, const std::string& select = MULTI_SELECT); - /// These functions use "bare bone" ODBC API calls (i.e. calls are not - /// "wrapped" in PocoData framework structures). + /// The above two functions use "bare bone" ODBC API calls + /// (i.e. calls are not "wrapped" in PocoData framework structures). /// The purpose of the functions is to verify that a driver behaves /// correctly as well as to determine its capabilities /// (e.g. SQLGetData() restrictions relaxation policy, if any). diff --git a/Data/include/Poco/Data/AbstractBinder.h b/Data/include/Poco/Data/AbstractBinder.h index fbdffbb7e..7076b50ce 100644 --- a/Data/include/Poco/Data/AbstractBinder.h +++ b/Data/include/Poco/Data/AbstractBinder.h @@ -45,6 +45,7 @@ #include "Poco/Data/Time.h" #include "Poco/Data/LOB.h" #include "Poco/DateTime.h" +#include "Poco/Nullable.h" #include "Poco/Any.h" #include "Poco/Dynamic/Var.h" #include @@ -57,10 +58,7 @@ namespace Poco { namespace Data { -enum NullData -{ - NULL_GENERIC = 0 -}; +typedef NullType NullData; namespace Keywords { diff --git a/Data/src/Statement.cpp b/Data/src/Statement.cpp index 86994dcf1..b0e0c736c 100644 --- a/Data/src/Statement.cpp +++ b/Data/src/Statement.cpp @@ -167,14 +167,16 @@ void Statement::setAsync(bool async) std::size_t Statement::wait(long milliseconds) { if (!_pResult) return 0; - + bool success = true; if (WAIT_FOREVER != milliseconds) - _pResult->wait(milliseconds); + success = _pResult->tryWait(milliseconds); else _pResult->wait(); if (_pResult->exception()) throw *_pResult->exception(); + else if (!success) + throw TimeoutException("Statement timed out."); return _pResult->data(); } diff --git a/Foundation/include/Poco/Nullable.h b/Foundation/include/Poco/Nullable.h index c31c28d84..66d941202 100644 --- a/Foundation/include/Poco/Nullable.h +++ b/Foundation/include/Poco/Nullable.h @@ -49,6 +49,12 @@ namespace Poco { +enum NullType +{ + NULL_GENERIC = 0 +}; + + template class Nullable /// Nullable is a simple wrapper class for value types @@ -81,6 +87,13 @@ public: { } + Nullable(const NullType&): + /// Creates an empty Nullable. + _value(), + _isNull(true) + { + } + Nullable(const C& value): /// Creates a Nullable with the given value. _value(value), @@ -116,6 +129,13 @@ public: return *this; } + Nullable& assign(NullType) + /// Sets value to null. + { + _isNull = true; + return *this; + } + Nullable& operator = (const C& value) /// Assigns a value to the Nullable. { @@ -128,6 +148,13 @@ public: return assign(other); } + Nullable& operator = (NullType) + /// Assigns another Nullable. + { + _isNull = true; + return *this; + } + void swap(Nullable& other) /// Swaps this Nullable with other. { @@ -135,30 +162,42 @@ public: std::swap(_isNull, other._isNull); } - bool operator==(const Nullable& other) const + bool operator == (const Nullable& other) const /// Compares two Nullables for equality { return (_isNull && other._isNull) || (_isNull == other._isNull && _value == other._value); } - bool operator==(const C& value) const + bool operator == (const C& value) const /// Compares Nullable with value for equality { return (!_isNull && _value == value); } - bool operator!=(const C& value) const + bool operator == (const NullType&) const + /// Compares Nullable with NullData for equality + { + return _isNull; + } + + bool operator != (const C& value) const /// Compares Nullable with value for non equality { return _value != value; } - bool operator!=(const Nullable& other) const + bool operator != (const Nullable& other) const /// Compares two Nullables for non equality { return !(*this == other); } + bool operator != (const NullType&) const + /// Compares with NullData for non equality + { + return !_isNull; + } + bool operator < (const Nullable& other) const /// Compares two Nullable objects. Return true if this object's /// value is smaler than the other object's value. @@ -223,6 +262,13 @@ public: return value(); } + operator NullType& () + /// Get reference to the value + { + + return _null; + } + bool isNull() const /// Returns true iff the Nullable is empty. { @@ -236,8 +282,9 @@ public: } private: - C _value; - bool _isNull; + C _value; + bool _isNull; + NullType _null; }; @@ -255,7 +302,39 @@ std::ostream& operator<<(std::ostream& out, const Nullable& obj) return out; } - + +template +bool operator == (const NullType&, const Nullable& n) + /// Returns true if this Nullable is null. +{ + return n.isNull(); +} + + +template +bool operator != (const C& c, const Nullable& n) + /// Compares Nullable with value for non equality +{ + return !(n == c); +} + + +template +bool operator == (const C& c, const Nullable& n) + /// Compares Nullable with NullData for equality +{ + return (n == c); +} + + +template +bool operator != (const NullType&, const Nullable& n) + /// Returns true if this Nullable is not null. +{ + return !n.isNull(); +} + + } // namespace Poco diff --git a/Foundation/testsuite/src/CoreTest.cpp b/Foundation/testsuite/src/CoreTest.cpp index 0f7329d2e..cc428947f 100644 --- a/Foundation/testsuite/src/CoreTest.cpp +++ b/Foundation/testsuite/src/CoreTest.cpp @@ -65,6 +65,7 @@ using Poco::Nullable; using Poco::Ascii; using Poco::BasicEvent; using Poco::delegate; +using Poco::NullType; using Poco::InvalidAccessException; @@ -828,6 +829,13 @@ void CoreTest::testNullable() assert (n2 < n1); assert (n2 != n1); assert (n1 > n2); + + NullType nd; + assert (n1 != nd); + assert (nd != n1); + n1.clear(); + assert (n1 == nd); + assert (nd == n1); }