mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-25 17:28:13 +02:00
fix(Data): Poco::Data::ODBC-dbEncoding property not used for insert/update #3396
This commit is contained in:
parent
87a1294c75
commit
08d68ea474
@ -71,7 +71,9 @@ public:
|
|||||||
Binder(const StatementHandle& rStmt,
|
Binder(const StatementHandle& rStmt,
|
||||||
std::size_t maxFieldSize,
|
std::size_t maxFieldSize,
|
||||||
ParameterBinding dataBinding = PB_IMMEDIATE,
|
ParameterBinding dataBinding = PB_IMMEDIATE,
|
||||||
const TypeInfo* pDataTypes = 0);
|
const TypeInfo* pDataTypes = 0,
|
||||||
|
Poco::TextEncoding::Ptr pFromEncoding = nullptr,
|
||||||
|
Poco::TextEncoding::Ptr pDBEncoding = nullptr);
|
||||||
/// Creates the Binder.
|
/// Creates the Binder.
|
||||||
|
|
||||||
~Binder();
|
~Binder();
|
||||||
@ -538,7 +540,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
void bindImplContainerString(std::size_t pos, const C& val, Direction dir)
|
void bindImplContainerString(std::size_t pos, const C& valC, Direction dir)
|
||||||
/// Utility function to bind containers of strings.
|
/// Utility function to bind containers of strings.
|
||||||
{
|
{
|
||||||
if (isOutBound(dir) || !isInBound(dir))
|
if (isOutBound(dir) || !isInBound(dir))
|
||||||
@ -547,7 +549,19 @@ private:
|
|||||||
if (PB_IMMEDIATE != _paramBinding)
|
if (PB_IMMEDIATE != _paramBinding)
|
||||||
throw InvalidAccessException("Containers can only be bound immediately.");
|
throw InvalidAccessException("Containers can only be bound immediately.");
|
||||||
|
|
||||||
std::size_t length = val.size();
|
const C* pVal = 0;
|
||||||
|
if (!transcodeRequired()) pVal = &valC;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pVal = new C(valC.size());
|
||||||
|
typename C::const_iterator valIt = valC.begin();
|
||||||
|
typename C::const_iterator valEnd = valC.end();
|
||||||
|
typename C::iterator tcIt = const_cast<C*>(pVal)->begin();
|
||||||
|
for (; valIt != valEnd; ++valIt, ++tcIt)
|
||||||
|
transcode(*valIt, *tcIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t length = pVal->size();
|
||||||
|
|
||||||
if (0 == length)
|
if (0 == length)
|
||||||
throw InvalidArgumentException("Empty container not allowed.");
|
throw InvalidArgumentException("Empty container not allowed.");
|
||||||
@ -560,7 +574,7 @@ private:
|
|||||||
|
|
||||||
if (size == _maxFieldSize)
|
if (size == _maxFieldSize)
|
||||||
{
|
{
|
||||||
getMinValueSize(val, size);
|
getMinValueSize(*pVal, size);
|
||||||
// accomodate for terminating zero
|
// accomodate for terminating zero
|
||||||
if (size != _maxFieldSize) ++size;
|
if (size != _maxFieldSize) ++size;
|
||||||
}
|
}
|
||||||
@ -574,20 +588,25 @@ private:
|
|||||||
if (_charPtrs.size() <= pos)
|
if (_charPtrs.size() <= pos)
|
||||||
_charPtrs.resize(pos + 1, 0);
|
_charPtrs.resize(pos + 1, 0);
|
||||||
|
|
||||||
_charPtrs[pos] = (char*) std::calloc(val.size() * size, sizeof(char));
|
_charPtrs[pos] = (char*) std::calloc(pVal->size() * size, sizeof(char));
|
||||||
|
|
||||||
|
std::string typeID = typeid(*pVal).name();
|
||||||
std::size_t strSize;
|
std::size_t strSize;
|
||||||
std::size_t offset = 0;
|
std::size_t offset = 0;
|
||||||
typename C::const_iterator it = val.begin();
|
typename C::const_iterator it = pVal->begin();
|
||||||
typename C::const_iterator end = val.end();
|
typename C::const_iterator end = pVal->end();
|
||||||
for (; it != end; ++it)
|
for (; it != end; ++it)
|
||||||
{
|
{
|
||||||
strSize = it->size();
|
strSize = it->size();
|
||||||
if (strSize > size)
|
if (strSize > size)
|
||||||
throw LengthExceededException("SQLBindParameter(std::vector<std::string>)");
|
{
|
||||||
|
if (transcodeRequired()) delete pVal;
|
||||||
|
throw LengthExceededException(Poco::format("SQLBindParameter(%s)", typeID));
|
||||||
|
}
|
||||||
std::memcpy(_charPtrs[pos] + offset, it->c_str(), strSize);
|
std::memcpy(_charPtrs[pos] + offset, it->c_str(), strSize);
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
|
if (transcodeRequired()) delete pVal;
|
||||||
|
|
||||||
if (Utility::isError(SQLBindParameter(_rStmt,
|
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||||
(SQLUSMALLINT) pos + 1,
|
(SQLUSMALLINT) pos + 1,
|
||||||
@ -600,7 +619,7 @@ private:
|
|||||||
(SQLINTEGER) size,
|
(SQLINTEGER) size,
|
||||||
&(*_vecLengthIndicator[pos])[0])))
|
&(*_vecLengthIndicator[pos])[0])))
|
||||||
{
|
{
|
||||||
throw StatementException(_rStmt, "SQLBindParameter(std::vector<std::string>)");
|
throw StatementException(_rStmt, Poco::format("SQLBindParameter(%s)", typeID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,8 @@ public:
|
|||||||
|
|
||||||
Extractor(const StatementHandle& rStmt,
|
Extractor(const StatementHandle& rStmt,
|
||||||
Preparator::Ptr pPreparator,
|
Preparator::Ptr pPreparator,
|
||||||
Poco::TextEncoding::Ptr pDBEncoding = nullptr);
|
Poco::TextEncoding::Ptr pDBEncoding = nullptr,
|
||||||
|
Poco::TextEncoding::Ptr pToEncoding = nullptr);
|
||||||
/// Creates the Extractor.
|
/// Creates the Extractor.
|
||||||
|
|
||||||
~Extractor();
|
~Extractor();
|
||||||
|
@ -30,7 +30,10 @@ namespace ODBC {
|
|||||||
Binder::Binder(const StatementHandle& rStmt,
|
Binder::Binder(const StatementHandle& rStmt,
|
||||||
std::size_t maxFieldSize,
|
std::size_t maxFieldSize,
|
||||||
Binder::ParameterBinding dataBinding,
|
Binder::ParameterBinding dataBinding,
|
||||||
const TypeInfo* pDataTypes):
|
const TypeInfo* pDataTypes,
|
||||||
|
Poco::TextEncoding::Ptr pFromEncoding,
|
||||||
|
Poco::TextEncoding::Ptr pDBEncoding):
|
||||||
|
Poco::Data::AbstractBinder(pFromEncoding, pDBEncoding),
|
||||||
_rStmt(rStmt),
|
_rStmt(rStmt),
|
||||||
_paramBinding(dataBinding),
|
_paramBinding(dataBinding),
|
||||||
_pTypeInfo(pDataTypes),
|
_pTypeInfo(pDataTypes),
|
||||||
@ -99,13 +102,30 @@ void Binder::freeMemory()
|
|||||||
DateTimeVecVec::iterator itDateTimeVec = _dateTimeVecVec.begin();
|
DateTimeVecVec::iterator itDateTimeVec = _dateTimeVecVec.begin();
|
||||||
DateTimeVecVec::iterator itDateTimeVecEnd = _dateTimeVecVec.end();
|
DateTimeVecVec::iterator itDateTimeVecEnd = _dateTimeVecVec.end();
|
||||||
for (; itDateTimeVec != itDateTimeVecEnd; ++itDateTimeVec) delete *itDateTimeVec;
|
for (; itDateTimeVec != itDateTimeVecEnd; ++itDateTimeVec) delete *itDateTimeVec;
|
||||||
|
|
||||||
|
if (transcodeRequired() && _inParams.size())
|
||||||
|
{
|
||||||
|
ParamMap::iterator itInParams = _inParams.begin();
|
||||||
|
ParamMap::iterator itInParamsEnd = _inParams.end();
|
||||||
|
for (; itInParams != itInParamsEnd; ++itInParams) free(itInParams->first);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
||||||
{
|
{
|
||||||
|
char* pTCVal = 0;
|
||||||
|
SQLINTEGER size = 0;
|
||||||
|
if (transcodeRequired())
|
||||||
|
{
|
||||||
|
std::string tcVal;
|
||||||
|
transcode(val, tcVal);
|
||||||
|
size = (SQLINTEGER)tcVal.size();
|
||||||
|
pTCVal = reinterpret_cast<char*>(std::calloc((size_t)size+1, 1));
|
||||||
|
std::memcpy(pTCVal, tcVal.data(), size);
|
||||||
|
}
|
||||||
|
else size = (SQLINTEGER)val.size();
|
||||||
SQLPOINTER pVal = 0;
|
SQLPOINTER pVal = 0;
|
||||||
SQLINTEGER size = (SQLINTEGER) val.size();
|
|
||||||
SQLINTEGER colSize = 0;
|
SQLINTEGER colSize = 0;
|
||||||
SQLSMALLINT decDigits = 0;
|
SQLSMALLINT decDigits = 0;
|
||||||
getColSizeAndPrecision(pos, SQL_C_CHAR, colSize, decDigits, val.size());
|
getColSizeAndPrecision(pos, SQL_C_CHAR, colSize, decDigits, val.size());
|
||||||
@ -120,9 +140,17 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
|||||||
}
|
}
|
||||||
else if (isInBound(dir))
|
else if (isInBound(dir))
|
||||||
{
|
{
|
||||||
pVal = (SQLPOINTER) val.c_str();
|
if (!pTCVal)
|
||||||
|
{
|
||||||
|
pVal = (SQLPOINTER)val.c_str();
|
||||||
_inParams.insert(ParamMap::value_type(pVal, size));
|
_inParams.insert(ParamMap::value_type(pVal, size));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pVal = (SQLPOINTER)pTCVal;
|
||||||
|
_inParams.insert(ParamMap::value_type(pVal, size));
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
throw InvalidArgumentException("Parameter must be [in] OR [out] bound.");
|
throw InvalidArgumentException("Parameter must be [in] OR [out] bound.");
|
||||||
|
|
||||||
@ -421,13 +449,29 @@ void Binder::synchronize()
|
|||||||
Utility::dateTimeSync(*it->second, *it->first);
|
Utility::dateTimeSync(*it->second, *it->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!transcodeRequired())
|
||||||
|
{
|
||||||
if (_strings.size())
|
if (_strings.size())
|
||||||
{
|
{
|
||||||
StringMap::iterator it = _strings.begin();
|
StringMap::iterator it = _strings.begin();
|
||||||
StringMap::iterator end = _strings.end();
|
StringMap::iterator end = _strings.end();
|
||||||
for(; it != end; ++it)
|
for (; it != end; ++it)
|
||||||
it->second->assign(it->first, std::strlen(it->first));
|
it->second->assign(it->first, std::strlen(it->first));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_strings.size())
|
||||||
|
{
|
||||||
|
StringMap::iterator it = _strings.begin();
|
||||||
|
StringMap::iterator end = _strings.end();
|
||||||
|
for (; it != end; ++it)
|
||||||
|
{
|
||||||
|
std::string str(it->first, std::strlen(it->first));
|
||||||
|
reverseTranscode(str, *it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_uuids.size())
|
if (_uuids.size())
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include "Poco/Data/ODBC/ConnectionHandle.h"
|
#include "Poco/Data/ODBC/ConnectionHandle.h"
|
||||||
#include "Poco/Data/ODBC/Utility.h"
|
#include "Poco/Data/ODBC/Utility.h"
|
||||||
#include "Poco/Data/ODBC/ODBCException.h"
|
#include "Poco/Data/ODBC/ODBCException.h"
|
||||||
|
#include "Poco/Error.h"
|
||||||
|
#include "Poco/Debugger.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@ -42,10 +44,11 @@ ConnectionHandle::~ConnectionHandle()
|
|||||||
{
|
{
|
||||||
SQLDisconnect(_hdbc);
|
SQLDisconnect(_hdbc);
|
||||||
SQLRETURN rc = SQLFreeHandle(SQL_HANDLE_DBC, _hdbc);
|
SQLRETURN rc = SQLFreeHandle(SQL_HANDLE_DBC, _hdbc);
|
||||||
|
|
||||||
if (_ownsEnvironment) delete _pEnvironment;
|
if (_ownsEnvironment) delete _pEnvironment;
|
||||||
|
#if defined(_DEBUG)
|
||||||
poco_assert (!Utility::isError(rc));
|
if (Utility::isError(rc))
|
||||||
|
Debugger::enter(Poco::Error::getMessage(Poco::Error::last()), __FILE__, __LINE__);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include "Poco/Data/ODBC/EnvironmentHandle.h"
|
#include "Poco/Data/ODBC/EnvironmentHandle.h"
|
||||||
#include "Poco/Data/ODBC/Utility.h"
|
#include "Poco/Data/ODBC/Utility.h"
|
||||||
#include "Poco/Data/ODBC/ODBCException.h"
|
#include "Poco/Data/ODBC/ODBCException.h"
|
||||||
|
#include "Poco/Error.h"
|
||||||
|
#include "Poco/Debugger.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@ -42,7 +44,10 @@ EnvironmentHandle::~EnvironmentHandle()
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
SQLRETURN rc = SQLFreeHandle(SQL_HANDLE_ENV, _henv);
|
SQLRETURN rc = SQLFreeHandle(SQL_HANDLE_ENV, _henv);
|
||||||
poco_assert (!Utility::isError(rc));
|
#if defined(_DEBUG)
|
||||||
|
if (Utility::isError(rc))
|
||||||
|
Debugger::enter(Poco::Error::getMessage(Poco::Error::last()), __FILE__, __LINE__);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
@ -35,7 +35,8 @@ const std::string Extractor::FLD_SIZE_EXCEEDED_FMT = "Specified data size (%z by
|
|||||||
|
|
||||||
Extractor::Extractor(const StatementHandle& rStmt,
|
Extractor::Extractor(const StatementHandle& rStmt,
|
||||||
Preparator::Ptr pPreparator,
|
Preparator::Ptr pPreparator,
|
||||||
TextEncoding::Ptr pDBEncoding): AbstractExtractor(pDBEncoding),
|
TextEncoding::Ptr pDBEncoding,
|
||||||
|
Poco::TextEncoding::Ptr pToEncoding): AbstractExtractor(pDBEncoding, pToEncoding),
|
||||||
_rStmt(rStmt),
|
_rStmt(rStmt),
|
||||||
_pPreparator(pPreparator),
|
_pPreparator(pPreparator),
|
||||||
_dataExtraction(pPreparator->getDataExtraction())
|
_dataExtraction(pPreparator->getDataExtraction())
|
||||||
@ -719,6 +720,7 @@ bool Extractor::extract(std::size_t pos, std::string& val)
|
|||||||
else
|
else
|
||||||
ret = extractBoundImpl(pos, result);
|
ret = extractBoundImpl(pos, result);
|
||||||
transcode(result, val);
|
transcode(result, val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -98,7 +98,8 @@ void ODBCStatementImpl::compileImpl()
|
|||||||
|
|
||||||
std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize"));
|
std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize"));
|
||||||
|
|
||||||
_pBinder = new Binder(_stmt, maxFieldSize, bind, pDT);
|
_pBinder = new Binder(_stmt, maxFieldSize, bind, pDT, TextEncoding::find("UTF-8"),
|
||||||
|
TextEncoding::find(Poco::RefAnyCast<std::string>(session().getProperty("dbEncoding"))));
|
||||||
|
|
||||||
makeInternalExtractors();
|
makeInternalExtractors();
|
||||||
doPrepare();
|
doPrepare();
|
||||||
@ -146,7 +147,8 @@ void ODBCStatementImpl::addPreparator()
|
|||||||
_preparations.push_back(new Preparator(*_preparations[0]));
|
_preparations.push_back(new Preparator(*_preparations[0]));
|
||||||
|
|
||||||
_extractors.push_back(new Extractor(_stmt, _preparations.back(),
|
_extractors.push_back(new Extractor(_stmt, _preparations.back(),
|
||||||
TextEncoding::find(Poco::RefAnyCast<std::string>(session().getProperty("dbEncoding")))));
|
TextEncoding::find(Poco::RefAnyCast<std::string>(session().getProperty("dbEncoding"))),
|
||||||
|
TextEncoding::find("UTF-8")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ using Poco::DateTime;
|
|||||||
|
|
||||||
|
|
||||||
ODBCTest::SessionPtr ODBCSQLServerTest::_pSession;
|
ODBCTest::SessionPtr ODBCSQLServerTest::_pSession;
|
||||||
|
ODBCTest::SessionPtr ODBCSQLServerTest::_pEncSession;
|
||||||
ODBCTest::ExecPtr ODBCSQLServerTest::_pExecutor;
|
ODBCTest::ExecPtr ODBCSQLServerTest::_pExecutor;
|
||||||
std::string ODBCSQLServerTest::_driver = MS_SQL_SERVER_ODBC_DRIVER;
|
std::string ODBCSQLServerTest::_driver = MS_SQL_SERVER_ODBC_DRIVER;
|
||||||
std::string ODBCSQLServerTest::_dsn = MS_SQL_SERVER_DSN;
|
std::string ODBCSQLServerTest::_dsn = MS_SQL_SERVER_DSN;
|
||||||
@ -733,13 +734,28 @@ void ODBCSQLServerTest::recreateUnicodeTable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ODBCSQLServerTest::recreateEncodingTables()
|
||||||
|
{
|
||||||
|
#if defined (POCO_ODBC_UNICODE)
|
||||||
|
dropObject("TABLE", "Latin1Table");
|
||||||
|
try { session() << "CREATE TABLE Latin1Table (str NVARCHAR(30))", now; }
|
||||||
|
catch (ConnectionException& ce) { std::cout << ce.toString() << std::endl; fail("recreateEncodingTables()"); }
|
||||||
|
catch (StatementException& se) { std::cout << se.toString() << std::endl; fail("recreateEncodingTables()"); }
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CppUnit::Test* ODBCSQLServerTest::suite()
|
CppUnit::Test* ODBCSQLServerTest::suite()
|
||||||
{
|
{
|
||||||
if ((_pSession = init(_driver, _dsn, _uid, _pwd, _connectString, _db)))
|
if ((_pSession = init(_driver, _dsn, _uid, _pwd, _connectString, _db)))
|
||||||
{
|
{
|
||||||
std::cout << "*** Connected to [" << _driver << "] test database." << std::endl;
|
std::cout << "*** Connected to [" << _driver << "] test database." << std::endl;
|
||||||
|
std::string enc = "Latin1";
|
||||||
|
if ((_pEncSession = init(_driver, _dsn, _uid, _pwd, _connectString, _db, enc)))
|
||||||
|
std::cout << "*** Connected to [" << _driver << "] test database, encoding: [" << enc << "]." << std::endl;
|
||||||
|
// ...
|
||||||
|
|
||||||
_pExecutor = new SQLExecutor(_driver + " SQL Executor", _pSession);
|
_pExecutor = new SQLExecutor(_driver + " SQL Executor", _pSession, _pEncSession);
|
||||||
|
|
||||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCSQLServerTest");
|
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCSQLServerTest");
|
||||||
|
|
||||||
@ -822,6 +838,7 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
|||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransactor);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransactor);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testNullable);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testNullable);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testUnicode);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testUnicode);
|
||||||
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testEncoding);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testReconnect);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
|
@ -74,8 +74,10 @@ private:
|
|||||||
void recreateMiscTable();
|
void recreateMiscTable();
|
||||||
void recreateLogTable();
|
void recreateLogTable();
|
||||||
void recreateUnicodeTable();
|
void recreateUnicodeTable();
|
||||||
|
void recreateEncodingTables();
|
||||||
|
|
||||||
static SessionPtr _pSession;
|
static SessionPtr _pSession;
|
||||||
|
static SessionPtr _pEncSession;
|
||||||
static ExecPtr _pExecutor;
|
static ExecPtr _pExecutor;
|
||||||
static std::string _driver;
|
static std::string _driver;
|
||||||
static std::string _dsn;
|
static std::string _dsn;
|
||||||
|
@ -1252,6 +1252,25 @@ void ODBCTest::testUnicode()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ODBCTest::testEncoding()
|
||||||
|
{
|
||||||
|
#if defined (POCO_ODBC_UNICODE)
|
||||||
|
if (!_pSession) fail("Test not available.");
|
||||||
|
|
||||||
|
for (int i = 0; i < 8;)
|
||||||
|
{
|
||||||
|
recreateEncodingTables();
|
||||||
|
_pSession->setFeature("autoBind", bindValue(i));
|
||||||
|
_pSession->setFeature("autoExtract", bindValue(i + 1));
|
||||||
|
_pExecutor->encoding(_rConnectString);
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::cout << "Not an UNICODE build, skipping." << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ODBCTest::testReconnect()
|
void ODBCTest::testReconnect()
|
||||||
{
|
{
|
||||||
if (!_pSession) fail ("Test not available.");
|
if (!_pSession) fail ("Test not available.");
|
||||||
@ -1341,7 +1360,8 @@ ODBCTest::SessionPtr ODBCTest::init(const std::string& driver,
|
|||||||
std::string& uid,
|
std::string& uid,
|
||||||
std::string& pwd,
|
std::string& pwd,
|
||||||
std::string& dbConnString,
|
std::string& dbConnString,
|
||||||
const std::string& db)
|
const std::string& db,
|
||||||
|
const std::string& dbEncoding)
|
||||||
{
|
{
|
||||||
Utility::drivers(_drivers);
|
Utility::drivers(_drivers);
|
||||||
if (!canConnect(driver, dsn, uid, pwd, dbConnString, db)) return 0;
|
if (!canConnect(driver, dsn, uid, pwd, dbConnString, db)) return 0;
|
||||||
@ -1349,7 +1369,10 @@ ODBCTest::SessionPtr ODBCTest::init(const std::string& driver,
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::cout << "Conecting to [" << dbConnString << ']' << std::endl;
|
std::cout << "Conecting to [" << dbConnString << ']' << std::endl;
|
||||||
return new Session(Poco::Data::ODBC::Connector::KEY, dbConnString, 5);
|
SessionPtr ptr = new Session(Poco::Data::ODBC::Connector::KEY, dbConnString, 5);
|
||||||
|
if (!dbEncoding.empty())
|
||||||
|
ptr->setProperty("dbEncoding", dbEncoding);
|
||||||
|
return ptr;
|
||||||
}catch (ConnectionFailedException& ex)
|
}catch (ConnectionFailedException& ex)
|
||||||
{
|
{
|
||||||
std::cout << ex.displayText() << std::endl;
|
std::cout << ex.displayText() << std::endl;
|
||||||
|
@ -151,6 +151,7 @@ public:
|
|||||||
virtual void testNullable();
|
virtual void testNullable();
|
||||||
|
|
||||||
virtual void testUnicode();
|
virtual void testUnicode();
|
||||||
|
virtual void testEncoding();
|
||||||
|
|
||||||
virtual void testReconnect();
|
virtual void testReconnect();
|
||||||
|
|
||||||
@ -177,13 +178,15 @@ protected:
|
|||||||
virtual void recreateMiscTable();
|
virtual void recreateMiscTable();
|
||||||
virtual void recreateLogTable();
|
virtual void recreateLogTable();
|
||||||
virtual void recreateUnicodeTable();
|
virtual void recreateUnicodeTable();
|
||||||
|
virtual void recreateEncodingTables();
|
||||||
|
|
||||||
static SessionPtr init(const std::string& driver,
|
static SessionPtr init(const std::string& driver,
|
||||||
std::string& dsn,
|
std::string& dsn,
|
||||||
std::string& uid,
|
std::string& uid,
|
||||||
std::string& pwd,
|
std::string& pwd,
|
||||||
std::string& dbConnString,
|
std::string& dbConnString,
|
||||||
const std::string& db = "");
|
const std::string& db = "",
|
||||||
|
const std::string& dbEncoding = "");
|
||||||
|
|
||||||
static bool canConnect(const std::string& driver,
|
static bool canConnect(const std::string& driver,
|
||||||
std::string& dsn,
|
std::string& dsn,
|
||||||
@ -374,6 +377,12 @@ inline void ODBCTest::recreateUnicodeTable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void ODBCTest::recreateEncodingTables()
|
||||||
|
{
|
||||||
|
throw Poco::NotImplementedException("ODBCTest::recreateUnicodeTables()");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool ODBCTest::bindValue(int i)
|
inline bool ODBCTest::bindValue(int i)
|
||||||
{
|
{
|
||||||
poco_assert (i < 8);
|
poco_assert (i < 8);
|
||||||
|
@ -296,9 +296,10 @@ const std::string SQLExecutor::MULTI_SELECT =
|
|||||||
"SELECT * FROM Test WHERE First = '5';";
|
"SELECT * FROM Test WHERE First = '5';";
|
||||||
|
|
||||||
|
|
||||||
SQLExecutor::SQLExecutor(const std::string& name, Poco::Data::Session* pSession):
|
SQLExecutor::SQLExecutor(const std::string& name, Poco::Data::Session* pSession, Poco::Data::Session* pEncSession):
|
||||||
CppUnit::TestCase(name),
|
CppUnit::TestCase(name),
|
||||||
_pSession(pSession)
|
_pSession(pSession),
|
||||||
|
_pEncSession(pEncSession)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3530,6 +3531,7 @@ void SQLExecutor::sqlLogger(const std::string& connect)
|
|||||||
rs.moveNext();
|
rs.moveNext();
|
||||||
assertTrue ("TestSQLChannel" == rs["Source"]);
|
assertTrue ("TestSQLChannel" == rs["Source"]);
|
||||||
assertTrue ("b Warning message" == rs["Text"]);
|
assertTrue ("b Warning message" == rs["Text"]);
|
||||||
|
root.setChannel(nullptr);
|
||||||
}
|
}
|
||||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("sqlLogger()"); }
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("sqlLogger()"); }
|
||||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("sqlLogger()"); }
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("sqlLogger()"); }
|
||||||
@ -4034,3 +4036,54 @@ void SQLExecutor::unicode(const std::string& dbConnString)
|
|||||||
Poco::UnicodeConverter::convert(wtext, text);
|
Poco::UnicodeConverter::convert(wtext, text);
|
||||||
assertTrue (text == std::string((const char*)supp));
|
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<std::string> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -87,7 +87,7 @@ public:
|
|||||||
DE_BOUND
|
DE_BOUND
|
||||||
};
|
};
|
||||||
|
|
||||||
SQLExecutor(const std::string& name, Poco::Data::Session* _pSession);
|
SQLExecutor(const std::string& name, Poco::Data::Session* pSession, Poco::Data::Session* pEncSession = 0);
|
||||||
~SQLExecutor();
|
~SQLExecutor();
|
||||||
|
|
||||||
void execute(const std::string& sql);
|
void execute(const std::string& sql);
|
||||||
@ -505,6 +505,7 @@ public:
|
|||||||
void nullable();
|
void nullable();
|
||||||
|
|
||||||
void unicode(const std::string& dbConnString);
|
void unicode(const std::string& dbConnString);
|
||||||
|
void encoding(const std::string& dbConnString);
|
||||||
|
|
||||||
void reconnect();
|
void reconnect();
|
||||||
|
|
||||||
@ -514,15 +515,24 @@ private:
|
|||||||
|
|
||||||
void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti);
|
void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti);
|
||||||
|
|
||||||
Poco::Data::Session& session();
|
Poco::Data::Session& session(bool enc = false);
|
||||||
Poco::Data::Session* _pSession;
|
Poco::Data::Session* _pSession;
|
||||||
|
Poco::Data::Session* _pEncSession;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline Poco::Data::Session& SQLExecutor::session()
|
inline Poco::Data::Session& SQLExecutor::session(bool enc)
|
||||||
{
|
{
|
||||||
poco_check_ptr (_pSession);
|
if (!enc)
|
||||||
|
{
|
||||||
|
poco_check_ptr(_pSession);
|
||||||
return *_pSession;
|
return *_pSession;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
poco_check_ptr(_pEncSession);
|
||||||
|
return *_pEncSession;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "Poco/Any.h"
|
#include "Poco/Any.h"
|
||||||
#include "Poco/Dynamic/Var.h"
|
#include "Poco/Dynamic/Var.h"
|
||||||
#include "Poco/UTFString.h"
|
#include "Poco/UTFString.h"
|
||||||
|
#include "Poco/TextEncoding.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -39,7 +40,7 @@ namespace Data {
|
|||||||
|
|
||||||
|
|
||||||
using NullData = NullType;
|
using NullData = NullType;
|
||||||
|
class Transcoder;
|
||||||
|
|
||||||
namespace Keywords {
|
namespace Keywords {
|
||||||
|
|
||||||
@ -64,7 +65,8 @@ public:
|
|||||||
PD_IN_OUT
|
PD_IN_OUT
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractBinder();
|
AbstractBinder(Poco::TextEncoding::Ptr pFromEncoding = nullptr,
|
||||||
|
Poco::TextEncoding::Ptr pDBEncoding = nullptr);
|
||||||
/// Creates the AbstractBinder.
|
/// Creates the AbstractBinder.
|
||||||
|
|
||||||
virtual ~AbstractBinder();
|
virtual ~AbstractBinder();
|
||||||
@ -356,6 +358,14 @@ public:
|
|||||||
|
|
||||||
static bool isInBound(Direction dir);
|
static bool isInBound(Direction dir);
|
||||||
/// Returns true if direction is in bound;
|
/// Returns true if direction is in bound;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool transcodeRequired() const;
|
||||||
|
void transcode(const std::string& from, std::string& to);
|
||||||
|
void reverseTranscode(const std::string& from, std::string& to);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Transcoder> _pTranscoder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -380,6 +390,12 @@ inline bool AbstractBinder::isInBound(Direction dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool AbstractBinder::transcodeRequired() const
|
||||||
|
{
|
||||||
|
return _pTranscoder.operator bool();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include "Poco/Data/LOB.h"
|
#include "Poco/Data/LOB.h"
|
||||||
#include "Poco/UUID.h"
|
#include "Poco/UUID.h"
|
||||||
#include "Poco/UTFString.h"
|
#include "Poco/UTFString.h"
|
||||||
#include "Poco/TextConverter.h"
|
|
||||||
#include "Poco/TextEncoding.h"
|
#include "Poco/TextEncoding.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -35,7 +34,6 @@
|
|||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
|
|
||||||
|
|
||||||
class DateTime;
|
class DateTime;
|
||||||
class Any;
|
class Any;
|
||||||
|
|
||||||
@ -48,6 +46,7 @@ namespace Data {
|
|||||||
|
|
||||||
class Date;
|
class Date;
|
||||||
class Time;
|
class Time;
|
||||||
|
class Transcoder;
|
||||||
|
|
||||||
|
|
||||||
class Data_API AbstractExtractor
|
class Data_API AbstractExtractor
|
||||||
@ -353,18 +352,18 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool transcodeRequired() const;
|
bool transcodeRequired() const;
|
||||||
void transcode(const std::string& val1, std::string& val2);
|
void transcode(const std::string& from, std::string& to);
|
||||||
|
void reverseTranscode(const std::string& from, std::string& to);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Poco::TextEncoding::Ptr _pDBEncoding;
|
std::unique_ptr<Transcoder> _pTranscoder;
|
||||||
Poco::TextEncoding::Ptr _pToEncoding;
|
|
||||||
std::unique_ptr<Poco::TextConverter> _pConverter;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// inlines
|
/// inlines
|
||||||
///
|
///
|
||||||
|
|
||||||
inline void AbstractExtractor::reset()
|
inline void AbstractExtractor::reset()
|
||||||
{
|
{
|
||||||
//default no-op
|
//default no-op
|
||||||
@ -373,17 +372,7 @@ inline void AbstractExtractor::reset()
|
|||||||
|
|
||||||
inline bool AbstractExtractor::transcodeRequired() const
|
inline bool AbstractExtractor::transcodeRequired() const
|
||||||
{
|
{
|
||||||
return _pConverter.operator bool();
|
return _pTranscoder.operator bool();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void AbstractExtractor::transcode(const std::string& val1, std::string& val2)
|
|
||||||
{
|
|
||||||
if (_pConverter)
|
|
||||||
{
|
|
||||||
val2.clear();
|
|
||||||
_pConverter->convert(val1, val2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class Binding: public AbstractBinding
|
|||||||
/// is passed to binding, the storage it refers to must be valid at the statement execution time.
|
/// is passed to binding, the storage it refers to must be valid at the statement execution time.
|
||||||
/// To pass a copy of a variable, constant or string literal, use utility function bind().
|
/// To pass a copy of a variable, constant or string literal, use utility function bind().
|
||||||
/// Variables can be passed as either copies or references (i.e. using either use() or bind()).
|
/// Variables can be passed as either copies or references (i.e. using either use() or bind()).
|
||||||
/// Constants, however, can only be passed as copies. this is best achieved using bind() utility
|
/// Constants, however, can only be passed as copies. This is best achieved using bind() utility
|
||||||
/// function. An attempt to pass a constant by reference shall result in compile-time error.
|
/// function. An attempt to pass a constant by reference shall result in compile-time error.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
97
Data/include/Poco/Data/Transcoder.h
Normal file
97
Data/include/Poco/Data/Transcoder.h
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
//
|
||||||
|
// Transcoder.h
|
||||||
|
//
|
||||||
|
// Library: Data
|
||||||
|
// Package: DataCore
|
||||||
|
// Module: Transcoder
|
||||||
|
//
|
||||||
|
// Definition of the Transcoder class.
|
||||||
|
//
|
||||||
|
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||||
|
// and Contributors.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef Data_Transcoder_INCLUDED
|
||||||
|
#define Data_Transcoder_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "Poco/Data/Data.h"
|
||||||
|
#include "Poco/TextConverter.h"
|
||||||
|
#include "Poco/TextEncoding.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Poco {
|
||||||
|
namespace Data {
|
||||||
|
|
||||||
|
|
||||||
|
class Data_API Transcoder
|
||||||
|
/// Utility class used to convert string data encoding.
|
||||||
|
///
|
||||||
|
/// The purpose of this class is to help with deciding
|
||||||
|
/// whether conversion is actually required, and to keep
|
||||||
|
/// the encodings lifetimes aligned with the converter lifetime.
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Ptr = std::unique_ptr<Transcoder>;
|
||||||
|
using ConverterPtr = std::unique_ptr<Poco::TextConverter>;
|
||||||
|
|
||||||
|
virtual ~Transcoder();
|
||||||
|
/// Destroys the Transcoder.
|
||||||
|
|
||||||
|
static Ptr create(Poco::TextEncoding::Ptr pFromEncoding = nullptr,
|
||||||
|
Poco::TextEncoding::Ptr pToEncoding = nullptr);
|
||||||
|
/// Returns a unique pointer to Transcode instance;
|
||||||
|
/// if there is no need for transcoding, null pointer
|
||||||
|
/// is returned.
|
||||||
|
|
||||||
|
std::string fromEncoding() const;
|
||||||
|
/// Returns "from" encoding canonical name.
|
||||||
|
|
||||||
|
std::string toEncoding() const;
|
||||||
|
/// Returns "from" encoding canonical name.
|
||||||
|
|
||||||
|
void transcode(const std::string& from, std::string& to);
|
||||||
|
/// Performs the conversion. Any prior content of the
|
||||||
|
/// destination string is cleared.
|
||||||
|
|
||||||
|
void reverseTranscode(const std::string& from, std::string& to);
|
||||||
|
/// Performs the reverse conversion. Any prior content of the
|
||||||
|
/// destination string is cleared.
|
||||||
|
|
||||||
|
private:
|
||||||
|
Transcoder(Poco::TextEncoding::Ptr pFromEncoding,
|
||||||
|
Poco::TextEncoding::Ptr pToEncoding);
|
||||||
|
/// Creates the Transcoder.
|
||||||
|
|
||||||
|
Poco::TextEncoding::Ptr _pFromEncoding;
|
||||||
|
Poco::TextEncoding::Ptr _pToEncoding;
|
||||||
|
ConverterPtr _pConverter;
|
||||||
|
ConverterPtr _pReverseConverter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// inlines
|
||||||
|
//
|
||||||
|
|
||||||
|
inline std::string Transcoder::fromEncoding() const
|
||||||
|
{
|
||||||
|
return _pFromEncoding->canonicalName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline std::string Transcoder::toEncoding() const
|
||||||
|
{
|
||||||
|
return _pToEncoding->canonicalName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} } // namespace Poco::Data
|
||||||
|
|
||||||
|
|
||||||
|
#endif // Data_Transcoder_INCLUDED
|
@ -16,6 +16,7 @@
|
|||||||
#include "Poco/Data/Date.h"
|
#include "Poco/Data/Date.h"
|
||||||
#include "Poco/Data/Time.h"
|
#include "Poco/Data/Time.h"
|
||||||
#include "Poco/Data/LOB.h"
|
#include "Poco/Data/LOB.h"
|
||||||
|
#include "Poco/Data/Transcoder.h"
|
||||||
#include "Poco/Data/DataException.h"
|
#include "Poco/Data/DataException.h"
|
||||||
#include "Poco/DateTime.h"
|
#include "Poco/DateTime.h"
|
||||||
#include "Poco/Any.h"
|
#include "Poco/Any.h"
|
||||||
@ -26,7 +27,9 @@ namespace Poco {
|
|||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
|
|
||||||
AbstractBinder::AbstractBinder()
|
AbstractBinder::AbstractBinder(Poco::TextEncoding::Ptr pFromEncoding,
|
||||||
|
Poco::TextEncoding::Ptr pDBEncoding) :
|
||||||
|
_pTranscoder(Transcoder::create(pFromEncoding, pDBEncoding))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,6 +39,20 @@ AbstractBinder::~AbstractBinder()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractBinder::transcode(const std::string& from, std::string& to)
|
||||||
|
{
|
||||||
|
if (_pTranscoder)
|
||||||
|
_pTranscoder->transcode(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractBinder::reverseTranscode(const std::string& from, std::string& to)
|
||||||
|
{
|
||||||
|
if (_pTranscoder)
|
||||||
|
_pTranscoder->reverseTranscode(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir)
|
void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir)
|
||||||
{
|
{
|
||||||
throw NotImplementedException("std::vector binder must be implemented.");
|
throw NotImplementedException("std::vector binder must be implemented.");
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/Data/AbstractExtractor.h"
|
#include "Poco/Data/AbstractExtractor.h"
|
||||||
|
#include "Poco/Data/Transcoder.h"
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
|
|
||||||
|
|
||||||
@ -22,16 +23,8 @@ namespace Data {
|
|||||||
|
|
||||||
AbstractExtractor::AbstractExtractor(Poco::TextEncoding::Ptr pDBEncoding,
|
AbstractExtractor::AbstractExtractor(Poco::TextEncoding::Ptr pDBEncoding,
|
||||||
Poco::TextEncoding::Ptr pToEncoding):
|
Poco::TextEncoding::Ptr pToEncoding):
|
||||||
_pDBEncoding(pDBEncoding),
|
_pTranscoder(Transcoder::create(pDBEncoding, pToEncoding))
|
||||||
_pToEncoding(pToEncoding ?
|
|
||||||
pToEncoding : _pDBEncoding ?
|
|
||||||
Poco::TextEncoding::find("UTF-8") : nullptr),
|
|
||||||
_pConverter(_pDBEncoding ?
|
|
||||||
new Poco::TextConverter(*pDBEncoding, *_pToEncoding) :
|
|
||||||
nullptr)
|
|
||||||
{
|
{
|
||||||
poco_assert_dbg((!_pDBEncoding && !_pToEncoding) ||
|
|
||||||
(_pDBEncoding && _pToEncoding));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -40,6 +33,20 @@ AbstractExtractor::~AbstractExtractor()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractExtractor::transcode(const std::string& from, std::string& to)
|
||||||
|
{
|
||||||
|
if (_pTranscoder)
|
||||||
|
_pTranscoder->transcode(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractExtractor::reverseTranscode(const std::string& from, std::string& to)
|
||||||
|
{
|
||||||
|
if (_pTranscoder)
|
||||||
|
_pTranscoder->reverseTranscode(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AbstractExtractor::extract(std::size_t pos, std::vector<Poco::Int8>& val)
|
bool AbstractExtractor::extract(std::size_t pos, std::vector<Poco::Int8>& val)
|
||||||
{
|
{
|
||||||
throw NotImplementedException("std::vector extractor must be implemented.");
|
throw NotImplementedException("std::vector extractor must be implemented.");
|
||||||
|
76
Data/src/Transcoder.cpp
Normal file
76
Data/src/Transcoder.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// Transcoder.cpp
|
||||||
|
//
|
||||||
|
// Library: Data
|
||||||
|
// Package: DataCore
|
||||||
|
// Module: Transcoder
|
||||||
|
//
|
||||||
|
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||||
|
// and Contributors.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include "Poco/Data/Transcoder.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Poco {
|
||||||
|
namespace Data {
|
||||||
|
|
||||||
|
|
||||||
|
Transcoder::Transcoder(Poco::TextEncoding::Ptr pFromEncoding,
|
||||||
|
Poco::TextEncoding::Ptr pToEncoding):
|
||||||
|
_pFromEncoding(pFromEncoding),
|
||||||
|
_pToEncoding(pToEncoding),
|
||||||
|
_pConverter(new Poco::TextConverter(*_pFromEncoding, *_pToEncoding)),
|
||||||
|
_pReverseConverter(new Poco::TextConverter(*_pToEncoding, *_pFromEncoding))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Transcoder::~Transcoder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Transcoder::Ptr Transcoder::create(Poco::TextEncoding::Ptr pFromEncoding,
|
||||||
|
Poco::TextEncoding::Ptr pToEncoding)
|
||||||
|
{
|
||||||
|
Ptr pTranscoder;
|
||||||
|
|
||||||
|
if (!pFromEncoding && !pToEncoding)
|
||||||
|
return pTranscoder;
|
||||||
|
|
||||||
|
if (!pFromEncoding) pFromEncoding = Poco::TextEncoding::find("UTF-8");
|
||||||
|
if (!pToEncoding) pToEncoding = Poco::TextEncoding::find("UTF-8");
|
||||||
|
|
||||||
|
if (pToEncoding->isA(pFromEncoding->canonicalName()))
|
||||||
|
return pTranscoder;
|
||||||
|
|
||||||
|
pTranscoder.reset(new Transcoder(pFromEncoding, pToEncoding));
|
||||||
|
return pTranscoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Transcoder::transcode(const std::string& from, std::string& to)
|
||||||
|
{
|
||||||
|
if (_pConverter)
|
||||||
|
{
|
||||||
|
to.clear();
|
||||||
|
_pConverter->convert(from, to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Transcoder::reverseTranscode(const std::string& from, std::string& to)
|
||||||
|
{
|
||||||
|
if (_pConverter)
|
||||||
|
{
|
||||||
|
to.clear();
|
||||||
|
_pReverseConverter->convert(from, to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} } // namespace Poco::Data
|
@ -1377,6 +1377,9 @@ void DataTest::testTranscode()
|
|||||||
assertTrue (ext.extract(0, utf8Out));
|
assertTrue (ext.extract(0, utf8Out));
|
||||||
assertTrue(utf8Out == latin1Text);
|
assertTrue(utf8Out == latin1Text);
|
||||||
|
|
||||||
|
Latin1Encoding::Ptr pe = new Latin1Encoding();
|
||||||
|
auto pUTF8E = Poco::TextEncoding::find("UTF-8");
|
||||||
|
|
||||||
Poco::Data::Test::Extractor ext2(new Latin1Encoding());
|
Poco::Data::Test::Extractor ext2(new Latin1Encoding());
|
||||||
ext2.setString(latin1Text);
|
ext2.setString(latin1Text);
|
||||||
utf8Out.clear();
|
utf8Out.clear();
|
||||||
|
@ -7,25 +7,25 @@ progen.libsuffix.release_static_md = md.lib
|
|||||||
progen.libsuffix.release_static_mt = mt.lib
|
progen.libsuffix.release_static_mt = mt.lib
|
||||||
progen.project.guidFromName.namespaceUUID = F4193868-E4EB-4090-9A01-344E7233004B
|
progen.project.guidFromName.namespaceUUID = F4193868-E4EB-4090-9A01-344E7233004B
|
||||||
|
|
||||||
progen.postprocess.upgrade2008to2015.tool = ${system.env.VS140COMNTOOLS}\\..\\IDE\\DevEnv.exe
|
progen.postprocess.upgrade2008to2015.tool = ${system.env.VS160COMNTOOLS}\\..\\IDE\\DevEnv.exe
|
||||||
progen.postprocess.upgrade2008to2015.args = %;/Upgrade
|
progen.postprocess.upgrade2008to2015.args = %;/Upgrade
|
||||||
progen.postprocess.upgrade2008to2015.deleteOriginalFile = true
|
progen.postprocess.upgrade2008to2015.deleteOriginalFile = true
|
||||||
progen.postprocess.upgrade2008to2015.deleteFiles = Backup;_UpgradeReport_Files;UpgradeLog.XML;UpgradeLog.htm
|
progen.postprocess.upgrade2008to2015.deleteFiles = Backup;_UpgradeReport_Files;UpgradeLog.XML;UpgradeLog.htm
|
||||||
progen.postprocess.upgrade2008to2015.fix2015ProjectFile = true
|
progen.postprocess.upgrade2008to2015.fix2015ProjectFile = true
|
||||||
|
|
||||||
progen.postprocess.upgrade2008to2017.tool = ${system.env.VS150COMNTOOLS}\\..\\IDE\\DevEnv.exe
|
progen.postprocess.upgrade2008to2017.tool = ${system.env.VS160COMNTOOLS}\\..\\IDE\\DevEnv.exe
|
||||||
progen.postprocess.upgrade2008to2017.args = %;/Upgrade
|
progen.postprocess.upgrade2008to2017.args = %;/Upgrade
|
||||||
progen.postprocess.upgrade2008to2017.deleteOriginalFile = true
|
progen.postprocess.upgrade2008to2017.deleteOriginalFile = true
|
||||||
progen.postprocess.upgrade2008to2017.deleteFiles = Backup;_UpgradeReport_Files;UpgradeLog.XML;UpgradeLog.htm
|
progen.postprocess.upgrade2008to2017.deleteFiles = Backup;_UpgradeReport_Files;UpgradeLog.XML;UpgradeLog.htm
|
||||||
progen.postprocess.upgrade2008to2017.fix2017ProjectFile = true
|
progen.postprocess.upgrade2008to2017.fix2017ProjectFile = true
|
||||||
|
|
||||||
progen.postprocess.upgrade2008to2019.tool = ${system.env.VS150COMNTOOLS}\\..\\IDE\\DevEnv.exe
|
progen.postprocess.upgrade2008to2019.tool = ${system.env.VS160COMNTOOLS}\\..\\IDE\\DevEnv.exe
|
||||||
progen.postprocess.upgrade2008to2019.args = %;/Upgrade
|
progen.postprocess.upgrade2008to2019.args = %;/Upgrade
|
||||||
progen.postprocess.upgrade2008to2019.deleteOriginalFile = true
|
progen.postprocess.upgrade2008to2019.deleteOriginalFile = true
|
||||||
progen.postprocess.upgrade2008to2019.deleteFiles = Backup;_UpgradeReport_Files;UpgradeLog.XML;UpgradeLog.htm
|
progen.postprocess.upgrade2008to2019.deleteFiles = Backup;_UpgradeReport_Files;UpgradeLog.XML;UpgradeLog.htm
|
||||||
progen.postprocess.upgrade2008to2019.fix2019ProjectFile = true
|
progen.postprocess.upgrade2008to2019.fix2019ProjectFile = true
|
||||||
|
|
||||||
progen.postprocess.upgrade2008to2022.tool = ${system.env.VS150COMNTOOLS}\\..\\IDE\\DevEnv.exe
|
progen.postprocess.upgrade2008to2022.tool = ${system.env.VS160COMNTOOLS}\\..\\IDE\\DevEnv.exe
|
||||||
progen.postprocess.upgrade2008to2022.args = %;/Upgrade
|
progen.postprocess.upgrade2008to2022.args = %;/Upgrade
|
||||||
progen.postprocess.upgrade2008to2022.deleteOriginalFile = true
|
progen.postprocess.upgrade2008to2022.deleteOriginalFile = true
|
||||||
progen.postprocess.upgrade2008to2022.deleteFiles = Backup;_UpgradeReport_Files;UpgradeLog.XML;UpgradeLog.htm
|
progen.postprocess.upgrade2008to2022.deleteFiles = Backup;_UpgradeReport_Files;UpgradeLog.XML;UpgradeLog.htm
|
||||||
|
Loading…
x
Reference in New Issue
Block a user