diff --git a/Data/ODBC/Makefile b/Data/ODBC/Makefile index d1d70e8a2..05c2f1648 100644 --- a/Data/ODBC/Makefile +++ b/Data/ODBC/Makefile @@ -5,6 +5,12 @@ # # Makefile for Poco ODBC # +# For Unicode support, add following to COMMONFLAGS: +# +# -DUNICODE +# +# Unicode is supported only for UnixODBC +# include $(POCO_BASE)/build/rules/global diff --git a/Data/ODBC/ODBC_VS71.vcproj b/Data/ODBC/ODBC_VS71.vcproj index 7a375c465..3cdd8ee4e 100644 --- a/Data/ODBC/ODBC_VS71.vcproj +++ b/Data/ODBC/ODBC_VS71.vcproj @@ -176,10 +176,10 @@ RelativePath=".\include\Poco\Data\Odbc\ODBC.h"> + RelativePath=".\include\Poco\Data\Odbc\ODBCException.h"> + RelativePath=".\include\Poco\Data\ODBC\ODBCMetaColumn.h"> @@ -200,10 +200,34 @@ RelativePath=".\include\Poco\Data\ODBC\Unicode.h"> + RelativePath=".\include\Poco\Data\ODBC\Unicode_UNIXODBC.h"> + + + + + + + + + + + + @@ -228,10 +252,10 @@ RelativePath=".\src\Extractor.cpp"> + RelativePath=".\src\ODBCException.cpp"> + RelativePath=".\src\ODBCMetaColumn.cpp"> @@ -252,7 +276,7 @@ RelativePath=".\src\Unicode.cpp"> + RelativePath=".\src\Unicode_UNIXODBC.cpp"> diff --git a/Data/ODBC/include/Poco/Data/ODBC/Unicode.h b/Data/ODBC/include/Poco/Data/ODBC/Unicode.h index b90e265d9..d7ca9f11a 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Unicode.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Unicode.h @@ -55,8 +55,10 @@ #if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) + #define POCO_ODBC_UNICODE #define POCO_ODBC_UNICODE_WINDOWS #elif defined(POCO_OS_FAMILY_UNIX) && defined(UNICODE) + #define POCO_ODBC_UNICODE #ifdef POCO_UNIXODBC #define POCO_ODBC_UNICODE_UNIXODBC #elif defined(POCO_IODBC) @@ -378,7 +380,7 @@ inline SQLINTEGER stringLength(SQLPOINTER pValue, SQLINTEGER length) } -#if !defined(POCO_ODBC_UNICODE_WINDOWS) && !defined(POCO_ODBC_UNICODE_UNIXODBC) +#if !defined(POCO_ODBC_UNICODE) /// diff --git a/Data/ODBC/include/Poco/Data/ODBC/Unicode_UNIXODBC.h b/Data/ODBC/include/Poco/Data/ODBC/Unicode_UNIXODBC.h index 160c68abc..1e4323641 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Unicode_UNIXODBC.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Unicode_UNIXODBC.h @@ -45,53 +45,28 @@ namespace Data { namespace ODBC { -inline void makeUTF16(SQLCHAR* pSQLChar, SQLINTEGER length, std::string& target) - /// Utility function for conversion from UTF-8 to UTF-16 -{ - int len = length; - if (SQL_NTS == len) - len = (int) std::strlen((const char *) pSQLChar); - - UTF8Encoding utf8Encoding; - UTF16Encoding utf16Encoding; - TextConverter converter(utf8Encoding, utf16Encoding); - - if (0 != converter.convert(pSQLChar, len, target)) - throw SyntaxException("Error converting UTF-8 to UTF-16"); -} +void makeUTF16(SQLCHAR* pSQLChar, SQLINTEGER length, std::string& target); + /// Utility function for conversion from ASCII to UTF-16 inline void makeUTF16(SQLCHAR* pSQLChar, SQLSMALLINT length, std::string& target) - /// Utility function for conversion from UTF-8 to UTF-16. + /// Utility function for conversion from ASCII to UTF-16. { makeUTF16(pSQLChar, (SQLINTEGER) length, target); } -inline void makeUTF8(Poco::Buffer& buffer, int length, SQLPOINTER pTarget, SQLINTEGER targetLength) -{ - UTF8Encoding utf8Encoding; - UTF16Encoding utf16Encoding; - TextConverter converter(utf16Encoding, utf8Encoding); - - std::string result; - if (0 != converter.convert(buffer.begin(), length, result)) - throw SyntaxException("Error converting UTF-16 to UTF-8"); - - std::memset(pTarget, 0, targetLength); - std::strncpy((char*) pTarget, result.c_str(), result.size() < targetLength ? result.size() : targetLength); -} +inline void makeUTF8(Poco::Buffer& buffer, int length, SQLPOINTER pTarget, SQLINTEGER targetLength); + /// Utility function for conversion from UTF-16 to ASCII. inline void makeUTF8(Poco::Buffer& buffer, int length, SQLPOINTER pTarget, SQLSMALLINT targetLength) + /// Utility function for conversion from UTF-16 to ASCII. { makeUTF8(buffer, length, pTarget, (SQLINTEGER) targetLength); } -#endif // POCO_ODBC_UNICODE - - } } } // namespace Poco::Data::ODBC diff --git a/Data/ODBC/src/Unicode_UNIXODBC.cpp b/Data/ODBC/src/Unicode_UNIXODBC.cpp index 099c3e536..3ff56c644 100644 --- a/Data/ODBC/src/Unicode_UNIXODBC.cpp +++ b/Data/ODBC/src/Unicode_UNIXODBC.cpp @@ -35,12 +35,19 @@ #include "Poco/Data/ODBC/ODBC.h" -#include "Poco/Data/ODBC/Unicode_UNIX.h" +#include "Poco/Data/ODBC/Unicode_UNIXODBC.h" +#include "Poco/TextConverter.h" +#include "Poco/UTF8Encoding.h" +#include "Poco/UTF16Encoding.h" #include "Poco/Buffer.h" #include "Poco/Exception.h" +#include using Poco::Buffer; +using Poco::UTF8Encoding; +using Poco::UTF16Encoding; +using Poco::TextConverter; using Poco::InvalidArgumentException; using Poco::NotImplementedException; @@ -50,6 +57,36 @@ namespace Data { namespace ODBC { +void makeUTF16(SQLCHAR* pSQLChar, SQLINTEGER length, std::string& target) +{ + int len = length; + if (SQL_NTS == len) + len = (int) std::strlen((const char *) pSQLChar); + + UTF8Encoding utf8Encoding; + UTF16Encoding utf16Encoding; + TextConverter converter(utf8Encoding, utf16Encoding); + + if (0 != converter.convert(pSQLChar, len, target)) + throw SyntaxException("Error converting UTF-8 to UTF-16"); +} + + +void makeUTF8(Poco::Buffer& buffer, int length, SQLPOINTER pTarget, SQLINTEGER targetLength) +{ + UTF8Encoding utf8Encoding; + UTF16Encoding utf16Encoding; + TextConverter converter(utf16Encoding, utf8Encoding); + + std::string result; + if (0 != converter.convert(buffer.begin(), length * sizeof(SQLWCHAR), result)) + throw SyntaxException("Error converting UTF-16 to UTF-8"); + + std::memset(pTarget, 0, targetLength); + std::strncpy((char*) pTarget, result.c_str(), result.size() < targetLength ? result.size() : targetLength); +} + + SQLRETURN SQLColAttribute(SQLHSTMT hstmt, SQLUSMALLINT iCol, SQLUSMALLINT iField, diff --git a/Data/ODBC/testsuite/Makefile b/Data/ODBC/testsuite/Makefile index 4838b898a..946e34d77 100644 --- a/Data/ODBC/testsuite/Makefile +++ b/Data/ODBC/testsuite/Makefile @@ -5,13 +5,21 @@ # # Makefile for Poco SQLite testsuite # +# For Unicode support, add following to COMMONFLAGS: +# +# -DUNICODE +# +# Unicode is supported only for UnixODBC +# include $(POCO_BASE)/build/rules/global ifeq (0, $(shell test -e /usr/lib/libodbc.so; echo $$?)) SYSLIBS += -lodbc -lodbcinst +COMMONFLAGS += -DPOCO_UNIXODBC else ifeq (0, $(shell test -e /usr/lib/libiodbc.so; echo $$?)) SYSLIBS += -liodbc -liodbcinst +COMMONFLAGS += -DPOCO_IODBC else $(error No ODBC library found. Please install unixODBC or iODBC and try again) endif diff --git a/Data/ODBC/testsuite/src/ODBCDB2Test.cpp b/Data/ODBC/testsuite/src/ODBCDB2Test.cpp index 1ff6e54fd..d7faa01ef 100644 --- a/Data/ODBC/testsuite/src/ODBCDB2Test.cpp +++ b/Data/ODBC/testsuite/src/ODBCDB2Test.cpp @@ -65,7 +65,7 @@ using Poco::NotFoundException; #define DB2_ODBC_DRIVER "IBM DB2 ODBC DRIVER - DB2COPY1" #define DB2_DSN "PocoDataDB2Test" -#define DB2_SERVER "localhost" +#define DB2_SERVER POCO_ODBC_TEST_DATABASE_SERVER #define DB2_PORT "50000" #define DB2_DB "POCOTEST" #define DB2_UID "db2admin" diff --git a/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp b/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp index b5a0d3179..ad60e1418 100644 --- a/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp @@ -65,7 +65,7 @@ using Poco::NotFoundException; #define MYSQL_ODBC_DRIVER "MySQL" #endif #define MYSQL_DSN "PocoDataMySQLTest" -#define MYSQL_SERVER "localhost" +#define MYSQL_SERVER POCO_ODBC_TEST_DATABASE_SERVER #define MYSQL_DB "test" #define MYSQL_UID "root" #define MYSQL_PWD "mysql" diff --git a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp index 7fd6ce59c..9cccba1c4 100644 --- a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp @@ -60,7 +60,7 @@ using Poco::DateTime; #define ORACLE_ODBC_DRIVER "Oracle in XE" #define ORACLE_DSN "PocoDataOracleTest" -#define ORACLE_SERVER "localhost" +#define ORACLE_SERVER POCO_ODBC_TEST_DATABASE_SERVER #define ORACLE_PORT "1521" #define ORACLE_SID "XE" #define ORACLE_UID "scott" diff --git a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp index 39eafc577..b70a8fdde 100644 --- a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp @@ -56,13 +56,13 @@ using Poco::DateTime; #ifdef POCO_ODBC_USE_MAMMOTH_NG #define POSTGRESQL_ODBC_DRIVER "Mammoth ODBCng Beta" -#elif defined (POCO_OS_FAMILY_WINDOWS) && defined (POCO_WIN32_UTF8) +#elif defined (POCO_ODBC_UNICODE) #define POSTGRESQL_ODBC_DRIVER "PostgreSQL Unicode" #else #define POSTGRESQL_ODBC_DRIVER "PostgreSQL ANSI" #endif #define POSTGRESQL_DSN "PocoDataPgSQLTest" -#define POSTGRESQL_SERVER "localhost" +#define POSTGRESQL_SERVER POCO_ODBC_TEST_DATABASE_SERVER #define POSTGRESQL_PORT "5432" #define POSTGRESQL_DB "postgres" #define POSTGRESQL_UID "postgres" diff --git a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp index 394f4bbee..f30541d76 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp @@ -69,7 +69,7 @@ using Poco::DateTime; #define MS_SQL_SERVER_ODBC_DRIVER "FreeTDS" #endif #define MS_SQL_SERVER_DSN "PocoDataSQLServerTest" -#define MS_SQL_SERVER_SERVER "localhost" +#define MS_SQL_SERVER_SERVER POCO_ODBC_TEST_DATABASE_SERVER #define MS_SQL_SERVER_PORT "1433" #define MS_SQL_SERVER_DB "test" #define MS_SQL_SERVER_UID "test" diff --git a/Data/ODBC/testsuite/src/ODBCTest.cpp b/Data/ODBC/testsuite/src/ODBCTest.cpp index efd5d9a5b..8d22760b8 100644 --- a/Data/ODBC/testsuite/src/ODBCTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCTest.cpp @@ -66,8 +66,8 @@ using Poco::DateTime; using Poco::NotFoundException; -ODBCTest::Drivers ODBCTest::_drivers; -const bool ODBCTest::_bindValues[8] = +ODBCTest::Drivers ODBCTest::_drivers; +const bool ODBCTest::_bindValues[8] = {true, true, true, false, false, true, false, false}; diff --git a/Data/ODBC/testsuite/src/ODBCTest.h b/Data/ODBC/testsuite/src/ODBCTest.h index b0bb0a6a3..62957faeb 100644 --- a/Data/ODBC/testsuite/src/ODBCTest.h +++ b/Data/ODBC/testsuite/src/ODBCTest.h @@ -44,11 +44,14 @@ #include "SQLExecutor.h" +#define POCO_ODBC_TEST_DATABASE_SERVER "localhost" + + class ODBCTest: public CppUnit::TestCase { public: - typedef Poco::SharedPtr SessionPtr; - typedef Poco::SharedPtr ExecPtr; + typedef Poco::SharedPtr SessionPtr; + typedef Poco::SharedPtr ExecPtr; ODBCTest(const std::string& name, SessionPtr pSession, diff --git a/Data/ODBC/testsuite/src/SQLExecutor.cpp b/Data/ODBC/testsuite/src/SQLExecutor.cpp index abe6bda8e..972be270e 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.cpp +++ b/Data/ODBC/testsuite/src/SQLExecutor.cpp @@ -2422,7 +2422,7 @@ void SQLExecutor::internalExtraction() i = rset.value("str0", 2); assert (5 == i); - const Column >& col = rset.column, InternalExtraction > >(0); + const Column >& col = rset.column >(0); Column >::Iterator it = col.begin(); Column >::Iterator end = col.end(); for (int i = 1; it != end; ++it, ++i) @@ -2456,7 +2456,7 @@ void SQLExecutor::internalExtraction() s = rset.value("cnt", 0).convert(); assert ("4" == s); - try { rset.column, InternalExtraction > >(100); fail ("must fail"); } + try { rset.column >(100); fail ("must fail"); } catch (RangeException&) { } try { rset.value(0,0); fail ("must fail"); } @@ -2465,7 +2465,7 @@ void SQLExecutor::internalExtraction() stmt = (session() << "DELETE FROM Vectors", now); rset = stmt; - try { rset.column, InternalExtraction > >(0); fail ("must fail"); } + try { rset.column >(0); fail ("must fail"); } catch (RangeException&) { } } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } diff --git a/Data/ODBC/testsuite/src/SQLExecutor.h b/Data/ODBC/testsuite/src/SQLExecutor.h index 9b20807af..61fe69877 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.h +++ b/Data/ODBC/testsuite/src/SQLExecutor.h @@ -44,6 +44,7 @@ #include "Poco/Data/BulkBinding.h" #include "Poco/NumberFormatter.h" #include "Poco/Exception.h" +#include #define poco_odbc_check_env(r, h) \