fix(Extractor): move extraction decoding to AbstractExtractor #3396

This commit is contained in:
Alex Fabijanic 2022-04-28 22:23:04 -05:00
parent 7f26310ef2
commit 4dfbcd33db
8 changed files with 91 additions and 20 deletions

View File

@ -33,7 +33,6 @@
#include "Poco/Nullable.h"
#include "Poco/UTFString.h"
#include "Poco/TextEncoding.h"
#include "Poco/TextConverter.h"
#include "Poco/Exception.h"
#include <map>
#ifdef POCO_OS_FAMILY_WINDOWS
@ -592,11 +591,10 @@ private:
val.clear();
if (ret)
{
Poco::TextConverter conv(*_pDBEncoding, *_pToEncoding);
val.resize(res.size());
typename C::iterator vIt = val.begin();
typename C::iterator it = res.begin();
for (; it != res.end(); ++it, ++vIt) conv.convert(*it, *vIt);
for (; it != res.end(); ++it, ++vIt) transcode(*it, *vIt);
}
return ret;
}
@ -607,7 +605,7 @@ private:
bool ret = false;
if (Preparator::DE_BOUND == _dataExtraction)
{
if (!_transcode)
if (!transcodeRequired())
ret = extractBoundImplContainer(pos, val);
else
ret = stringContainerExtractConvert(pos, val);
@ -628,9 +626,6 @@ private:
PreparatorPtr _pPreparator;
Preparator::DataExtraction _dataExtraction;
std::vector<SQLLEN> _lengths;
Poco::TextEncoding::Ptr _pDBEncoding;
bool _transcode;
Poco::TextEncoding::Ptr _pToEncoding;
};

View File

@ -35,13 +35,10 @@ const std::string Extractor::FLD_SIZE_EXCEEDED_FMT = "Specified data size (%z by
Extractor::Extractor(const StatementHandle& rStmt,
Preparator::Ptr pPreparator,
TextEncoding::Ptr pDBEncoding):
TextEncoding::Ptr pDBEncoding): AbstractExtractor(pDBEncoding),
_rStmt(rStmt),
_pPreparator(pPreparator),
_dataExtraction(pPreparator->getDataExtraction()),
_pDBEncoding(pDBEncoding),
_transcode(_pDBEncoding && !_pDBEncoding->isA("UTF-8")),
_pToEncoding(_transcode ? Poco::TextEncoding::find("UTF-8") : nullptr)
_dataExtraction(pPreparator->getDataExtraction())
{
}
@ -707,7 +704,7 @@ bool Extractor::extract(std::size_t pos, std::string& val)
{
bool ret = false;
if (!_transcode)
if (!transcodeRequired())
{
if (Preparator::DE_MANUAL == _dataExtraction)
ret = extractManualImpl(pos, val, SQL_C_CHAR);
@ -721,8 +718,7 @@ bool Extractor::extract(std::size_t pos, std::string& val)
ret = extractManualImpl(pos, result, SQL_C_CHAR);
else
ret = extractBoundImpl(pos, result);
Poco::TextConverter converter(*_pDBEncoding, *_pToEncoding);
converter.convert(result, val);
transcode(result, val);
}
return ret;

View File

@ -23,6 +23,9 @@
#include "Poco/Data/LOB.h"
#include "Poco/UUID.h"
#include "Poco/UTFString.h"
#include "Poco/TextConverter.h"
#include "Poco/TextEncoding.h"
#include <memory>
#include <vector>
#include <deque>
#include <list>
@ -54,7 +57,8 @@ class Data_API AbstractExtractor
public:
using Ptr = SharedPtr<AbstractExtractor>;
AbstractExtractor();
AbstractExtractor(Poco::TextEncoding::Ptr pDBEncoding = nullptr,
Poco::TextEncoding::Ptr pToEncoding = nullptr);
/// Creates the AbstractExtractor.
virtual ~AbstractExtractor();
@ -346,6 +350,15 @@ public:
virtual void reset();
/// Resets any information internally cached by the extractor.
protected:
bool transcodeRequired() const;
void transcode(const std::string& val1, std::string& val2);
private:
Poco::TextEncoding::Ptr _pDBEncoding;
Poco::TextEncoding::Ptr _pToEncoding;
std::unique_ptr<Poco::TextConverter> _pConverter;
};
@ -358,6 +371,22 @@ inline void AbstractExtractor::reset()
}
inline bool AbstractExtractor::transcodeRequired() const
{
return _pConverter.operator bool();
}
inline void AbstractExtractor::transcode(const std::string& val1, std::string& val2)
{
if (_pConverter)
{
val2.clear();
_pConverter->convert(val1, val2);
}
}
} } // namespace Poco::Data

View File

@ -20,8 +20,18 @@ namespace Poco {
namespace Data {
AbstractExtractor::AbstractExtractor()
AbstractExtractor::AbstractExtractor(Poco::TextEncoding::Ptr pDBEncoding,
Poco::TextEncoding::Ptr pToEncoding):
_pDBEncoding(pDBEncoding),
_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));
}

View File

@ -9,6 +9,7 @@
#include "DataTest.h"
#include "Extractor.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
#include "Poco/Data/Session.h"
@ -29,6 +30,7 @@
#include "Poco/Dynamic/Var.h"
#include "Poco/Data/DynamicLOB.h"
#include "Poco/Data/DynamicDateTime.h"
#include "Poco/Latin1Encoding.h"
#include "Poco/Exception.h"
#include <cstring>
#include <sstream>
@ -45,6 +47,7 @@ using Poco::UInt32;
using Poco::Int64;
using Poco::UInt64;
using Poco::DateTime;
using Poco::Latin1Encoding;
using Poco::Dynamic::Var;
using Poco::InvalidAccessException;
using Poco::IllegalStateException;
@ -65,6 +68,7 @@ using Poco::Data::Row;
using Poco::Data::SimpleRowFormatter;
using Poco::Data::Date;
using Poco::Data::Time;
using Poco::Data::AbstractExtractor;
using Poco::Data::AbstractExtraction;
using Poco::Data::AbstractExtractionVec;
using Poco::Data::AbstractExtractionVecVec;
@ -1358,6 +1362,29 @@ void DataTest::testExternalBindingAndExtraction()
}
void DataTest::testTranscode()
{
Latin1Encoding::Ptr pL2E = new Latin1Encoding();
const unsigned char latin1Chars[] = { 'g', 252, 'n', 't', 'e', 'r', 0 };
const unsigned char utf8Chars[] = { 'g', 195, 188, 'n', 't', 'e', 'r', 0 };
std::string latin1Text((const char*)latin1Chars);
std::string utf8Text((const char*)utf8Chars);
Poco::Data::Test::Extractor ext;
ext.setString(latin1Text);
std::string utf8Out;
assertTrue (ext.extract(0, utf8Out));
assertTrue(utf8Out == latin1Text);
Poco::Data::Test::Extractor ext2(new Latin1Encoding());
ext2.setString(latin1Text);
utf8Out.clear();
assertTrue(ext2.extract(0, utf8Out));
assertTrue(utf8Out == utf8Text);
}
void DataTest::setUp()
{
}
@ -1388,6 +1415,7 @@ CppUnit::Test* DataTest::suite()
CppUnit_addTest(pSuite, DataTest, testRowFormat);
CppUnit_addTest(pSuite, DataTest, testDateAndTime);
CppUnit_addTest(pSuite, DataTest, testExternalBindingAndExtraction);
CppUnit_addTest(pSuite, DataTest, testTranscode);
return pSuite;
}

View File

@ -43,6 +43,7 @@ public:
void testRowFormat();
void testDateAndTime();
void testExternalBindingAndExtraction();
void testTranscode();
void setUp();
void tearDown();

View File

@ -18,7 +18,8 @@ namespace Data {
namespace Test {
Extractor::Extractor()
Extractor::Extractor(Poco::TextEncoding::Ptr pDBEncoding):
AbstractExtractor(pDBEncoding)
{
}
@ -130,7 +131,10 @@ bool Extractor::extract(std::size_t pos, char& val)
bool Extractor::extract(std::size_t pos, std::string& val)
{
val = "";
if (!transcodeRequired())
val = _stringValue;
else
transcode(_stringValue, val);
return true;
}

View File

@ -26,7 +26,7 @@ class Extractor: public Poco::Data::AbstractExtractor
/// A no-op implementation of AbstractExtractor for testing.
{
public:
Extractor();
Extractor(Poco::TextEncoding::Ptr pDBEncoding = nullptr);
/// Creates the Extractor.
~Extractor();
@ -110,6 +110,14 @@ public:
/// Returns true if the current row value at pos column is null.
void reset();
void setString(const std::string& str)
{
_stringValue = str;
}
private:
std::string _stringValue;
};