mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-16 15:01:15 +02:00
GH #290: Unicode support
This commit is contained in:
parent
8b39a87fd6
commit
1aa28e1491
@ -67,6 +67,7 @@ Release 1.5.3 (2014-05-xx)
|
|||||||
- fixed GH #442: Use correct prefix length field of Windows IP_ADAPTER_PREFIX structure
|
- fixed GH #442: Use correct prefix length field of Windows IP_ADAPTER_PREFIX structure
|
||||||
- improved GH #328: NetworkInterface on Windows XP
|
- improved GH #328: NetworkInterface on Windows XP
|
||||||
- fixed GH #154 Add support for MYSQL_TYPE_NEWDECIMAL to Poco::Data::MySQL
|
- fixed GH #154 Add support for MYSQL_TYPE_NEWDECIMAL to Poco::Data::MySQL
|
||||||
|
- fixed GH #290: Unicode support
|
||||||
|
|
||||||
Release 1.5.2 (2013-09-16)
|
Release 1.5.2 (2013-09-16)
|
||||||
==========================
|
==========================
|
||||||
|
@ -252,6 +252,18 @@ public:
|
|||||||
void bind(std::size_t pos, const std::list<std::string>& val, Direction dir);
|
void bind(std::size_t pos, const std::list<std::string>& val, Direction dir);
|
||||||
/// Binds a string list.
|
/// Binds a string list.
|
||||||
|
|
||||||
|
void bind(std::size_t pos, const UTF16String& val, Direction dir);
|
||||||
|
/// Binds a string.
|
||||||
|
|
||||||
|
void bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir);
|
||||||
|
/// Binds a string vector.
|
||||||
|
|
||||||
|
void bind(std::size_t pos, const std::deque<UTF16String>& val, Direction dir);
|
||||||
|
/// Binds a string deque.
|
||||||
|
|
||||||
|
void bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir);
|
||||||
|
/// Binds a string list.
|
||||||
|
|
||||||
void bind(std::size_t pos, const BLOB& val, Direction dir);
|
void bind(std::size_t pos, const BLOB& val, Direction dir);
|
||||||
/// Binds a BLOB. In-bound only.
|
/// Binds a BLOB. In-bound only.
|
||||||
|
|
||||||
@ -341,18 +353,20 @@ public:
|
|||||||
/// Clears the cached storage.
|
/// Clears the cached storage.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<SQLLEN*> LengthVec;
|
typedef std::vector<SQLLEN*> LengthVec;
|
||||||
typedef std::vector<std::vector<SQLLEN> > LengthVecVec;
|
typedef std::vector<std::vector<SQLLEN> > LengthVecVec;
|
||||||
typedef std::vector<char*> CharPtrVec;
|
typedef std::vector<char*> CharPtrVec;
|
||||||
typedef std::vector<bool*> BoolPtrVec;
|
typedef std::vector<UTF16Char*> UTF16CharPtrVec;
|
||||||
typedef std::vector<std::vector<SQL_DATE_STRUCT> > DateVec;
|
typedef std::vector<bool*> BoolPtrVec;
|
||||||
typedef std::vector<std::vector<SQL_TIME_STRUCT> > TimeVec;
|
typedef std::vector<std::vector<SQL_DATE_STRUCT> > DateVec;
|
||||||
typedef std::vector<std::vector<SQL_TIMESTAMP_STRUCT> > DateTimeVec;
|
typedef std::vector<std::vector<SQL_TIME_STRUCT> > TimeVec;
|
||||||
typedef std::vector<std::vector<Poco::Any> > AnyVec;
|
typedef std::vector<std::vector<SQL_TIMESTAMP_STRUCT> > DateTimeVec;
|
||||||
typedef std::map<char*, std::string*> StringMap;
|
typedef std::vector<std::vector<Poco::Any> > AnyVec;
|
||||||
typedef std::map<SQL_DATE_STRUCT*, Date*> DateMap;
|
typedef std::map<char*, std::string*> StringMap;
|
||||||
typedef std::map<SQL_TIME_STRUCT*, Time*> TimeMap;
|
typedef std::map<UTF16String::value_type*, UTF16String*> UTF16StringMap;
|
||||||
typedef std::map<SQL_TIMESTAMP_STRUCT*, DateTime*> TimestampMap;
|
typedef std::map<SQL_DATE_STRUCT*, Date*> DateMap;
|
||||||
|
typedef std::map<SQL_TIME_STRUCT*, Time*> TimeMap;
|
||||||
|
typedef std::map<SQL_TIMESTAMP_STRUCT*, DateTime*> TimestampMap;
|
||||||
|
|
||||||
void describeParameter(std::size_t pos);
|
void describeParameter(std::size_t pos);
|
||||||
/// Sets the description field for the parameter, if needed.
|
/// Sets the description field for the parameter, if needed.
|
||||||
@ -581,6 +595,71 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename C>
|
||||||
|
void bindImplContainerUTF16String(std::size_t pos, const C& val, Direction dir)
|
||||||
|
/// Utility function to bind containers of strings.
|
||||||
|
{
|
||||||
|
if (isOutBound(dir) || !isInBound(dir))
|
||||||
|
throw NotImplementedException("String container parameter type can only be inbound.");
|
||||||
|
|
||||||
|
if (PB_IMMEDIATE != _paramBinding)
|
||||||
|
throw InvalidAccessException("Containers can only be bound immediately.");
|
||||||
|
|
||||||
|
if (0 == val.size())
|
||||||
|
throw InvalidArgumentException("Empty container not allowed.");
|
||||||
|
|
||||||
|
setParamSetSize(val.size());
|
||||||
|
|
||||||
|
SQLINTEGER size = 0;
|
||||||
|
getColumnOrParameterSize(pos, size);
|
||||||
|
poco_assert(size > 0);
|
||||||
|
|
||||||
|
if (size == _maxFieldSize)
|
||||||
|
{
|
||||||
|
getMinValueSize(val, size);
|
||||||
|
// accomodate for terminating zero
|
||||||
|
if (size != _maxFieldSize) size += sizeof(UTF16Char);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_vecLengthIndicator.size() <= pos)
|
||||||
|
{
|
||||||
|
_vecLengthIndicator.resize(pos + 1);
|
||||||
|
_vecLengthIndicator[pos].resize(val.size(), SQL_NTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_utf16CharPtrs.size() <= pos)
|
||||||
|
_utf16CharPtrs.resize(pos + 1, 0);
|
||||||
|
|
||||||
|
_utf16CharPtrs[pos] = (UTF16Char*)std::calloc(val.size() * size, sizeof(UTF16Char));
|
||||||
|
|
||||||
|
std::size_t strSize;
|
||||||
|
std::size_t offset = 0;
|
||||||
|
typename C::const_iterator it = val.begin();
|
||||||
|
typename C::const_iterator end = val.end();
|
||||||
|
for (; it != end; ++it)
|
||||||
|
{
|
||||||
|
strSize = it->size() * sizeof(UTF16Char);
|
||||||
|
if (strSize > size)
|
||||||
|
throw LengthExceededException("SQLBindParameter(std::vector<UTF16String>)");
|
||||||
|
std::memcpy(_utf16CharPtrs[pos] + offset, it->data(), strSize);
|
||||||
|
offset += (size / sizeof(UTF16Char));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||||
|
(SQLUSMALLINT)pos + 1,
|
||||||
|
toODBCDirection(dir),
|
||||||
|
SQL_C_WCHAR,
|
||||||
|
SQL_WLONGVARCHAR,
|
||||||
|
(SQLUINTEGER)size - 1,
|
||||||
|
0,
|
||||||
|
_utf16CharPtrs[pos],
|
||||||
|
(SQLINTEGER)size,
|
||||||
|
&_vecLengthIndicator[pos][0])))
|
||||||
|
{
|
||||||
|
throw StatementException(_rStmt, "SQLBindParameter(std::vector<UTF16String>)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
void bindImplContainerLOB(std::size_t pos, const C& val, Direction dir)
|
void bindImplContainerLOB(std::size_t pos, const C& val, Direction dir)
|
||||||
{
|
{
|
||||||
@ -859,7 +938,7 @@ private:
|
|||||||
typename T::const_iterator end = val.end();
|
typename T::const_iterator end = val.end();
|
||||||
for (; it != end; ++it)
|
for (; it != end; ++it)
|
||||||
{
|
{
|
||||||
std::size_t sz = it->size();
|
std::size_t sz = it->size() * sizeof(T);
|
||||||
if (sz > _maxFieldSize)
|
if (sz > _maxFieldSize)
|
||||||
throw LengthExceededException();
|
throw LengthExceededException();
|
||||||
|
|
||||||
@ -888,11 +967,13 @@ private:
|
|||||||
TimeMap _times;
|
TimeMap _times;
|
||||||
TimestampMap _timestamps;
|
TimestampMap _timestamps;
|
||||||
StringMap _strings;
|
StringMap _strings;
|
||||||
|
UTF16StringMap _utf16Strings;
|
||||||
|
|
||||||
DateVec _dateVec;
|
DateVec _dateVec;
|
||||||
TimeVec _timeVec;
|
TimeVec _timeVec;
|
||||||
DateTimeVec _dateTimeVec;
|
DateTimeVec _dateTimeVec;
|
||||||
CharPtrVec _charPtrs;
|
CharPtrVec _charPtrs;
|
||||||
|
UTF16CharPtrVec _utf16CharPtrs;
|
||||||
BoolPtrVec _boolPtrs;
|
BoolPtrVec _boolPtrs;
|
||||||
const TypeInfo* _pTypeInfo;
|
const TypeInfo* _pTypeInfo;
|
||||||
SQLINTEGER _paramSetSize;
|
SQLINTEGER _paramSetSize;
|
||||||
@ -1241,6 +1322,24 @@ inline void Binder::bind(std::size_t pos, const std::list<std::string>& val, Dir
|
|||||||
bindImplContainerString(pos, val, dir);
|
bindImplContainerString(pos, val, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Binder::bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir)
|
||||||
|
{
|
||||||
|
bindImplContainerUTF16String(pos, val, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Binder::bind(std::size_t pos, const std::deque<UTF16String>& val, Direction dir)
|
||||||
|
{
|
||||||
|
bindImplContainerUTF16String(pos, val, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Binder::bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir)
|
||||||
|
{
|
||||||
|
bindImplContainerUTF16String(pos, val, dir);
|
||||||
|
}
|
||||||
|
|
||||||
inline void Binder::bind(std::size_t pos, const BLOB& val, Direction dir)
|
inline void Binder::bind(std::size_t pos, const BLOB& val, Direction dir)
|
||||||
{
|
{
|
||||||
bindImplLOB<BLOB>(pos, val, dir);
|
bindImplLOB<BLOB>(pos, val, dir);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "Poco/Any.h"
|
#include "Poco/Any.h"
|
||||||
#include "Poco/Dynamic/Var.h"
|
#include "Poco/Dynamic/Var.h"
|
||||||
#include "Poco/Nullable.h"
|
#include "Poco/Nullable.h"
|
||||||
|
#include "Poco/UTFString.h"
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#ifdef POCO_OS_FAMILY_WINDOWS
|
#ifdef POCO_OS_FAMILY_WINDOWS
|
||||||
@ -232,6 +233,19 @@ public:
|
|||||||
|
|
||||||
bool extract(std::size_t pos, std::list<std::string>& val);
|
bool extract(std::size_t pos, std::list<std::string>& val);
|
||||||
/// Extracts a string list.
|
/// Extracts a string list.
|
||||||
|
/// Extracts a single character list.
|
||||||
|
|
||||||
|
bool extract(std::size_t pos, UTF16String& val);
|
||||||
|
/// Extracts a string.
|
||||||
|
|
||||||
|
bool extract(std::size_t pos, std::vector<UTF16String>& val);
|
||||||
|
/// Extracts a string vector.
|
||||||
|
|
||||||
|
bool extract(std::size_t pos, std::deque<UTF16String>& val);
|
||||||
|
/// Extracts a string deque.
|
||||||
|
|
||||||
|
bool extract(std::size_t pos, std::list<UTF16String>& val);
|
||||||
|
/// Extracts a string list.
|
||||||
|
|
||||||
bool extract(std::size_t pos, Poco::Data::BLOB& val);
|
bool extract(std::size_t pos, Poco::Data::BLOB& val);
|
||||||
/// Extracts a BLOB.
|
/// Extracts a BLOB.
|
||||||
@ -372,7 +386,10 @@ private:
|
|||||||
|
|
||||||
bool extractBoundImplContainer(std::size_t pos, std::vector<std::string>& values);
|
bool extractBoundImplContainer(std::size_t pos, std::vector<std::string>& values);
|
||||||
bool extractBoundImplContainer(std::size_t pos, std::deque<std::string>& values);
|
bool extractBoundImplContainer(std::size_t pos, std::deque<std::string>& values);
|
||||||
bool extractBoundImplContainer(std::size_t pos, std::list<std::string>& values);
|
bool extractBoundImplContainer(std::size_t pos, std::list<std::string>& values);
|
||||||
|
bool extractBoundImplContainer(std::size_t pos, std::vector<Poco::UTF16String>& values);
|
||||||
|
bool extractBoundImplContainer(std::size_t pos, std::deque<Poco::UTF16String>& values);
|
||||||
|
bool extractBoundImplContainer(std::size_t pos, std::list<Poco::UTF16String>& values);
|
||||||
bool extractBoundImplContainer(std::size_t pos, std::vector<Poco::Data::CLOB>& values);
|
bool extractBoundImplContainer(std::size_t pos, std::vector<Poco::Data::CLOB>& values);
|
||||||
bool extractBoundImplContainer(std::size_t pos, std::deque<Poco::Data::CLOB>& values);
|
bool extractBoundImplContainer(std::size_t pos, std::deque<Poco::Data::CLOB>& values);
|
||||||
bool extractBoundImplContainer(std::size_t pos, std::list<Poco::Data::CLOB>& values);
|
bool extractBoundImplContainer(std::size_t pos, std::list<Poco::Data::CLOB>& values);
|
||||||
@ -394,7 +411,19 @@ private:
|
|||||||
ItType it = values.begin();
|
ItType it = values.begin();
|
||||||
ItType end = values.end();
|
ItType end = values.end();
|
||||||
for (int row = 0; it != end; ++it, ++row)
|
for (int row = 0; it != end; ++it, ++row)
|
||||||
it->assign(*pc + row * colWidth, _pPreparator->actualDataSize(pos, row));
|
{
|
||||||
|
it->assign(*pc + row * colWidth / sizeof(CharType), _pPreparator->actualDataSize(pos, row));
|
||||||
|
// clean up superfluous null chars returned by some drivers
|
||||||
|
typename StringType::size_type trimLen = 0;
|
||||||
|
typename StringType::reverse_iterator sIt = it->rbegin();
|
||||||
|
typename StringType::reverse_iterator sEnd = it->rend();
|
||||||
|
for (; sIt != sEnd; ++sIt)
|
||||||
|
{
|
||||||
|
if (*sIt == '\0') ++trimLen;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
if (trimLen) it->assign(it->begin(), it->begin() + it->length() - trimLen);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -522,6 +551,9 @@ private:
|
|||||||
case MetaColumn::FDT_STRING:
|
case MetaColumn::FDT_STRING:
|
||||||
{ return extAny<T, std::string>(pos, val); }
|
{ return extAny<T, std::string>(pos, val); }
|
||||||
|
|
||||||
|
case MetaColumn::FDT_WSTRING:
|
||||||
|
{ return extAny<T, Poco::UTF16String>(pos, val); }
|
||||||
|
|
||||||
case MetaColumn::FDT_BLOB:
|
case MetaColumn::FDT_BLOB:
|
||||||
{ return extAny<T, Poco::Data::BLOB>(pos, val); }
|
{ return extAny<T, Poco::Data::BLOB>(pos, val); }
|
||||||
|
|
||||||
@ -592,6 +624,24 @@ inline bool Extractor::extractBoundImplContainer(std::size_t pos, std::list<std:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Extractor::extractBoundImplContainer(std::size_t pos, std::vector<Poco::UTF16String>& values)
|
||||||
|
{
|
||||||
|
return extractBoundImplContainerString(pos, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Extractor::extractBoundImplContainer(std::size_t pos, std::deque<Poco::UTF16String>& values)
|
||||||
|
{
|
||||||
|
return extractBoundImplContainerString(pos, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Extractor::extractBoundImplContainer(std::size_t pos, std::list<Poco::UTF16String>& values)
|
||||||
|
{
|
||||||
|
return extractBoundImplContainerString(pos, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool Extractor::extractBoundImplContainer(std::size_t pos,
|
inline bool Extractor::extractBoundImplContainer(std::size_t pos,
|
||||||
std::vector<Poco::Data::CLOB>& values)
|
std::vector<Poco::Data::CLOB>& values)
|
||||||
{
|
{
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "Poco/DynamicAny.h"
|
#include "Poco/DynamicAny.h"
|
||||||
#include "Poco/DateTime.h"
|
#include "Poco/DateTime.h"
|
||||||
#include "Poco/SharedPtr.h"
|
#include "Poco/SharedPtr.h"
|
||||||
|
#include "Poco/UTFString.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#ifdef POCO_OS_FAMILY_WINDOWS
|
#ifdef POCO_OS_FAMILY_WINDOWS
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -87,8 +88,10 @@ public:
|
|||||||
DT_BOOL,
|
DT_BOOL,
|
||||||
DT_BOOL_ARRAY,
|
DT_BOOL_ARRAY,
|
||||||
DT_CHAR,
|
DT_CHAR,
|
||||||
|
DT_WCHAR,
|
||||||
DT_UCHAR,
|
DT_UCHAR,
|
||||||
DT_CHAR_ARRAY,
|
DT_CHAR_ARRAY,
|
||||||
|
DT_WCHAR_ARRAY,
|
||||||
DT_UCHAR_ARRAY,
|
DT_UCHAR_ARRAY,
|
||||||
DT_DATE,
|
DT_DATE,
|
||||||
DT_TIME,
|
DT_TIME,
|
||||||
@ -280,6 +283,18 @@ public:
|
|||||||
void prepare(std::size_t pos, const std::list<std::string>& val);
|
void prepare(std::size_t pos, const std::list<std::string>& val);
|
||||||
/// Prepares a string list.
|
/// Prepares a string list.
|
||||||
|
|
||||||
|
void prepare(std::size_t pos, const UTF16String& val);
|
||||||
|
/// Prepares a string.
|
||||||
|
|
||||||
|
void prepare(std::size_t pos, const std::vector<UTF16String>& val);
|
||||||
|
/// Prepares a string vector.
|
||||||
|
|
||||||
|
void prepare(std::size_t pos, const std::deque<UTF16String>& val);
|
||||||
|
/// Prepares a string deque.
|
||||||
|
|
||||||
|
void prepare(std::size_t pos, const std::list<UTF16String>& val);
|
||||||
|
/// Prepares a string list.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::Data::BLOB& val);
|
void prepare(std::size_t pos, const Poco::Data::BLOB& val);
|
||||||
/// Prepares a BLOB.
|
/// Prepares a BLOB.
|
||||||
|
|
||||||
@ -490,6 +505,15 @@ private:
|
|||||||
else
|
else
|
||||||
return prepareVariableLen<char>(pos, SQL_C_CHAR, maxDataSize(pos), DT_CHAR);
|
return prepareVariableLen<char>(pos, SQL_C_CHAR, maxDataSize(pos), DT_CHAR);
|
||||||
|
|
||||||
|
case MetaColumn::FDT_WSTRING:
|
||||||
|
{
|
||||||
|
typedef UTF16String::value_type CharType;
|
||||||
|
if (pVal)
|
||||||
|
return prepareCharArray<CharType, DT_WCHAR_ARRAY>(pos, SQL_C_WCHAR, maxDataSize(pos), pVal->size());
|
||||||
|
else
|
||||||
|
return prepareVariableLen<CharType>(pos, SQL_C_WCHAR, maxDataSize(pos), DT_WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
case MetaColumn::FDT_BLOB:
|
case MetaColumn::FDT_BLOB:
|
||||||
{
|
{
|
||||||
typedef Poco::Data::BLOB::ValueType CharType;
|
typedef Poco::Data::BLOB::ValueType CharType;
|
||||||
@ -1007,6 +1031,30 @@ inline void Preparator::prepare(std::size_t pos, const std::list<std::string>& v
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Preparator::prepare(std::size_t pos, const UTF16String&)
|
||||||
|
{
|
||||||
|
prepareVariableLen<UTF16String::value_type>(pos, SQL_C_WCHAR, maxDataSize(pos), DT_CHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Preparator::prepare(std::size_t pos, const std::vector<UTF16String>& val)
|
||||||
|
{
|
||||||
|
prepareCharArray<UTF16String::value_type, DT_WCHAR_ARRAY>(pos, SQL_C_WCHAR, maxDataSize(pos), val.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Preparator::prepare(std::size_t pos, const std::deque<UTF16String>& val)
|
||||||
|
{
|
||||||
|
prepareCharArray<UTF16String::value_type, DT_WCHAR_ARRAY>(pos, SQL_C_WCHAR, maxDataSize(pos), val.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Preparator::prepare(std::size_t pos, const std::list<UTF16String>& val)
|
||||||
|
{
|
||||||
|
prepareCharArray<UTF16String::value_type, DT_WCHAR_ARRAY>(pos, SQL_C_WCHAR, maxDataSize(pos), val.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void Preparator::prepare(std::size_t pos, const Poco::Data::BLOB&)
|
inline void Preparator::prepare(std::size_t pos, const Poco::Data::BLOB&)
|
||||||
{
|
{
|
||||||
prepareVariableLen<Poco::Data::BLOB::ValueType>(pos, SQL_C_BINARY, maxDataSize(pos), DT_UCHAR);
|
prepareVariableLen<Poco::Data::BLOB::ValueType>(pos, SQL_C_BINARY, maxDataSize(pos), DT_UCHAR);
|
||||||
|
@ -73,6 +73,10 @@ void Binder::freeMemory()
|
|||||||
CharPtrVec::iterator endChr = _charPtrs.end();
|
CharPtrVec::iterator endChr = _charPtrs.end();
|
||||||
for (; itChr != endChr; ++itChr) std::free(*itChr);
|
for (; itChr != endChr; ++itChr) std::free(*itChr);
|
||||||
|
|
||||||
|
UTF16CharPtrVec::iterator itUTF16Chr = _utf16CharPtrs.begin();
|
||||||
|
UTF16CharPtrVec::iterator endUTF16Chr = _utf16CharPtrs.end();
|
||||||
|
for (; itUTF16Chr != endUTF16Chr; ++itUTF16Chr) std::free(*itUTF16Chr);
|
||||||
|
|
||||||
BoolPtrVec::iterator itBool = _boolPtrs.begin();
|
BoolPtrVec::iterator itBool = _boolPtrs.begin();
|
||||||
BoolPtrVec::iterator endBool = _boolPtrs.end();
|
BoolPtrVec::iterator endBool = _boolPtrs.end();
|
||||||
for (; itBool != endBool; ++itBool) delete [] *itBool;
|
for (; itBool != endBool; ++itBool) delete [] *itBool;
|
||||||
@ -127,6 +131,58 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Binder::bind(std::size_t pos, const UTF16String& val, Direction dir)
|
||||||
|
{
|
||||||
|
typedef UTF16String::value_type CharT;
|
||||||
|
|
||||||
|
SQLPOINTER pVal = 0;
|
||||||
|
SQLINTEGER size = (SQLINTEGER)(val.size() * sizeof(CharT));
|
||||||
|
|
||||||
|
if (isOutBound(dir))
|
||||||
|
{
|
||||||
|
getColumnOrParameterSize(pos, size);
|
||||||
|
CharT* pChar = (CharT*)std::calloc(size, 1);
|
||||||
|
pVal = (SQLPOINTER)pChar;
|
||||||
|
_outParams.insert(ParamMap::value_type(pVal, size));
|
||||||
|
_utf16Strings.insert(UTF16StringMap::value_type(pChar, const_cast<UTF16String*>(&val)));
|
||||||
|
}
|
||||||
|
else if (isInBound(dir))
|
||||||
|
{
|
||||||
|
pVal = (SQLPOINTER)val.c_str();
|
||||||
|
_inParams.insert(ParamMap::value_type(pVal, size));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw InvalidArgumentException("Parameter must be [in] OR [out] bound.");
|
||||||
|
|
||||||
|
SQLLEN* pLenIn = new SQLLEN;
|
||||||
|
SQLINTEGER colSize = 0;
|
||||||
|
SQLSMALLINT decDigits = 0;
|
||||||
|
getColSizeAndPrecision(pos, SQL_C_WCHAR, colSize, decDigits);
|
||||||
|
*pLenIn = SQL_NTS;
|
||||||
|
|
||||||
|
if (PB_AT_EXEC == _paramBinding)
|
||||||
|
{
|
||||||
|
*pLenIn = SQL_LEN_DATA_AT_EXEC(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
_lengthIndicator.push_back(pLenIn);
|
||||||
|
|
||||||
|
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||||
|
(SQLUSMALLINT)pos + 1,
|
||||||
|
toODBCDirection(dir),
|
||||||
|
SQL_C_WCHAR,
|
||||||
|
SQL_WLONGVARCHAR,
|
||||||
|
(SQLUINTEGER)colSize,
|
||||||
|
0,
|
||||||
|
pVal,
|
||||||
|
(SQLINTEGER)size,
|
||||||
|
_lengthIndicator.back())))
|
||||||
|
{
|
||||||
|
throw StatementException(_rStmt, "SQLBindParameter(std::string)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Binder::bind(std::size_t pos, const Date& val, Direction dir)
|
void Binder::bind(std::size_t pos, const Date& val, Direction dir)
|
||||||
{
|
{
|
||||||
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT);
|
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT);
|
||||||
|
@ -64,6 +64,22 @@ bool Extractor::extractBoundImpl<std::string>(std::size_t pos, std::string& val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
bool Extractor::extractBoundImpl<UTF16String>(std::size_t pos, UTF16String& val)
|
||||||
|
{
|
||||||
|
typedef UTF16String::value_type CharT;
|
||||||
|
if (isNull(pos)) return false;
|
||||||
|
std::size_t dataSize = _pPreparator->actualDataSize(pos);
|
||||||
|
CharT* sp = AnyCast<CharT*>(_pPreparator->at(pos));
|
||||||
|
std::size_t len = Poco::UnicodeConverter::UTFStrlen(sp);
|
||||||
|
if (len < dataSize) dataSize = len;
|
||||||
|
checkDataSize(dataSize);
|
||||||
|
val.assign(sp, dataSize);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
bool Extractor::extractBoundImpl<Poco::Data::Date>(std::size_t pos, Poco::Data::Date& val)
|
bool Extractor::extractBoundImpl<Poco::Data::Date>(std::size_t pos, Poco::Data::Date& val)
|
||||||
{
|
{
|
||||||
@ -280,6 +296,61 @@ bool Extractor::extractManualImpl<std::string>(std::size_t pos, std::string& val
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
bool Extractor::extractManualImpl<UTF16String>(std::size_t pos, UTF16String& val, SQLSMALLINT cType)
|
||||||
|
{
|
||||||
|
std::size_t maxSize = _pPreparator->getMaxFieldSize();
|
||||||
|
std::size_t fetchedSize = 0;
|
||||||
|
std::size_t totalSize = 0;
|
||||||
|
|
||||||
|
SQLLEN len;
|
||||||
|
const int bufSize = CHUNK_SIZE;
|
||||||
|
Poco::Buffer<UTF16String::value_type> apChar(bufSize);
|
||||||
|
UTF16String::value_type* pChar = apChar.begin();
|
||||||
|
SQLRETURN rc = 0;
|
||||||
|
|
||||||
|
val.clear();
|
||||||
|
resizeLengths(pos);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::memset(pChar, 0, bufSize);
|
||||||
|
len = 0;
|
||||||
|
rc = SQLGetData(_rStmt,
|
||||||
|
(SQLUSMALLINT)pos + 1,
|
||||||
|
cType, //C data type
|
||||||
|
pChar, //returned value
|
||||||
|
bufSize, //buffer length
|
||||||
|
&len); //length indicator
|
||||||
|
|
||||||
|
if (SQL_NO_DATA != rc && Utility::isError(rc))
|
||||||
|
throw StatementException(_rStmt, "SQLGetData()");
|
||||||
|
|
||||||
|
if (SQL_NO_TOTAL == len)//unknown length, throw
|
||||||
|
throw UnknownDataLengthException("Could not determine returned data length.");
|
||||||
|
|
||||||
|
if (isNullLengthIndicator(len))
|
||||||
|
{
|
||||||
|
_lengths[pos] = len;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SQL_NO_DATA == rc || !len)
|
||||||
|
break;
|
||||||
|
|
||||||
|
_lengths[pos] += len;
|
||||||
|
fetchedSize = _lengths[pos] > CHUNK_SIZE ? CHUNK_SIZE : _lengths[pos];
|
||||||
|
totalSize += fetchedSize;
|
||||||
|
if (totalSize <= maxSize)
|
||||||
|
val.append(pChar, fetchedSize / sizeof(UTF16Char));
|
||||||
|
else
|
||||||
|
throw DataException(format(FLD_SIZE_EXCEEDED_FMT, fetchedSize, maxSize));
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
bool Extractor::extractManualImpl<Poco::Data::CLOB>(std::size_t pos,
|
bool Extractor::extractManualImpl<Poco::Data::CLOB>(std::size_t pos,
|
||||||
Poco::Data::CLOB& val,
|
Poco::Data::CLOB& val,
|
||||||
@ -608,6 +679,42 @@ bool Extractor::extract(std::size_t pos, std::list<std::string>& val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Extractor::extract(std::size_t pos, UTF16String& val)
|
||||||
|
{
|
||||||
|
if (Preparator::DE_MANUAL == _dataExtraction)
|
||||||
|
return extractManualImpl(pos, val, SQL_C_WCHAR);
|
||||||
|
else
|
||||||
|
return extractBoundImpl(pos, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Extractor::extract(std::size_t pos, std::vector<UTF16String>& val)
|
||||||
|
{
|
||||||
|
if (Preparator::DE_BOUND == _dataExtraction)
|
||||||
|
return extractBoundImplContainer(pos, val);
|
||||||
|
else
|
||||||
|
throw InvalidAccessException("Direct container extraction only allowed for bound mode.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Extractor::extract(std::size_t pos, std::deque<UTF16String>& val)
|
||||||
|
{
|
||||||
|
if (Preparator::DE_BOUND == _dataExtraction)
|
||||||
|
return extractBoundImplContainer(pos, val);
|
||||||
|
else
|
||||||
|
throw InvalidAccessException("Direct container extraction only allowed for bound mode.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Extractor::extract(std::size_t pos, std::list<UTF16String>& val)
|
||||||
|
{
|
||||||
|
if (Preparator::DE_BOUND == _dataExtraction)
|
||||||
|
return extractBoundImplContainer(pos, val);
|
||||||
|
else
|
||||||
|
throw InvalidAccessException("Direct container extraction only allowed for bound mode.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
|
bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
|
||||||
{
|
{
|
||||||
if (Preparator::DE_MANUAL == _dataExtraction)
|
if (Preparator::DE_MANUAL == _dataExtraction)
|
||||||
|
@ -83,14 +83,16 @@ void ODBCMetaColumn::init()
|
|||||||
{
|
{
|
||||||
case SQL_BIT:
|
case SQL_BIT:
|
||||||
setType(MetaColumn::FDT_BOOL); break;
|
setType(MetaColumn::FDT_BOOL); break;
|
||||||
|
|
||||||
case SQL_CHAR:
|
case SQL_CHAR:
|
||||||
case SQL_VARCHAR:
|
case SQL_VARCHAR:
|
||||||
case SQL_LONGVARCHAR:
|
case SQL_LONGVARCHAR:
|
||||||
case -8:// PostgreSQL CHAR (with size specified - psqlODBC)
|
|
||||||
case -9:// SQL Server NVARCHAR
|
|
||||||
case -10:// PostgreSQL VARCHAR (without size specified)
|
|
||||||
setType(MetaColumn::FDT_STRING); break;
|
setType(MetaColumn::FDT_STRING); break;
|
||||||
|
|
||||||
|
case SQL_WCHAR:
|
||||||
|
case SQL_WVARCHAR:
|
||||||
|
case SQL_WLONGVARCHAR:
|
||||||
|
setType(MetaColumn::FDT_WSTRING); break;
|
||||||
|
|
||||||
case SQL_TINYINT:
|
case SQL_TINYINT:
|
||||||
setType(MetaColumn::FDT_INT8); break;
|
setType(MetaColumn::FDT_INT8); break;
|
||||||
|
@ -72,6 +72,10 @@ void Preparator::freeMemory() const
|
|||||||
deleteCachedArray<char>(it->first);
|
deleteCachedArray<char>(it->first);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DT_WCHAR:
|
||||||
|
deleteCachedArray<UTF16String>(it->first);
|
||||||
|
break;
|
||||||
|
|
||||||
case DT_UCHAR:
|
case DT_UCHAR:
|
||||||
deleteCachedArray<unsigned char>(it->first);
|
deleteCachedArray<unsigned char>(it->first);
|
||||||
break;
|
break;
|
||||||
@ -83,6 +87,13 @@ void Preparator::freeMemory() const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DT_WCHAR_ARRAY:
|
||||||
|
{
|
||||||
|
UTF16String::value_type** pc = AnyCast<UTF16String::value_type*>(&_values[it->first]);
|
||||||
|
if (pc) std::free(*pc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case DT_UCHAR_ARRAY:
|
case DT_UCHAR_ARRAY:
|
||||||
{
|
{
|
||||||
unsigned char** pc = AnyCast<unsigned char*>(&_values[it->first]);
|
unsigned char** pc = AnyCast<unsigned char*>(&_values[it->first]);
|
||||||
|
@ -834,6 +834,17 @@ void ODBCOracleTest::recreateLogTable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ODBCOracleTest::recreateUnicodeTable()
|
||||||
|
{
|
||||||
|
#if defined (POCO_ODBC_UNICODE)
|
||||||
|
dropObject("TABLE", "UnicodeTable");
|
||||||
|
try { session() << "CREATE TABLE UnicodeTable (str NVARCHAR2(30))", now; }
|
||||||
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail("recreateUnicodeTable()"); }
|
||||||
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail("recreateUnicodeTable()"); }
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CppUnit::Test* ODBCOracleTest::suite()
|
CppUnit::Test* ODBCOracleTest::suite()
|
||||||
{
|
{
|
||||||
if ((_pSession = init(_driver, _dsn, _uid, _pwd, _connectString)))
|
if ((_pSession = init(_driver, _dsn, _uid, _pwd, _connectString)))
|
||||||
@ -923,6 +934,7 @@ CppUnit::Test* ODBCOracleTest::suite()
|
|||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testTransaction);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testTransactor);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testTransactor);
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testNullable);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testNullable);
|
||||||
|
CppUnit_addTest(pSuite, ODBCOracleTest, testUnicode);
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testReconnect);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
|
@ -70,6 +70,7 @@ private:
|
|||||||
void recreateNullsTable(const std::string& notNull = "");
|
void recreateNullsTable(const std::string& notNull = "");
|
||||||
void recreateMiscTable();
|
void recreateMiscTable();
|
||||||
void recreateLogTable();
|
void recreateLogTable();
|
||||||
|
void recreateUnicodeTable();
|
||||||
|
|
||||||
static ODBCTest::SessionPtr _pSession;
|
static ODBCTest::SessionPtr _pSession;
|
||||||
static ODBCTest::ExecPtr _pExecutor;
|
static ODBCTest::ExecPtr _pExecutor;
|
||||||
|
@ -53,6 +53,10 @@ using Poco::DateTime;
|
|||||||
#define POSTGRESQL_DSN "PocoDataPgSQLTest"
|
#define POSTGRESQL_DSN "PocoDataPgSQLTest"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||||
|
#pragma message ("Using " POSTGRESQL_ODBC_DRIVER " driver.")
|
||||||
|
#endif
|
||||||
|
|
||||||
#define POSTGRESQL_SERVER POCO_ODBC_TEST_DATABASE_SERVER
|
#define POSTGRESQL_SERVER POCO_ODBC_TEST_DATABASE_SERVER
|
||||||
#define POSTGRESQL_PORT "5432"
|
#define POSTGRESQL_PORT "5432"
|
||||||
#define POSTGRESQL_DB "postgres"
|
#define POSTGRESQL_DB "postgres"
|
||||||
@ -559,6 +563,17 @@ void ODBCPostgreSQLTest::recreateLogTable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ODBCPostgreSQLTest::recreateUnicodeTable()
|
||||||
|
{
|
||||||
|
#if defined (POCO_ODBC_UNICODE)
|
||||||
|
dropObject("TABLE", "UnicodeTable");
|
||||||
|
try { session() << "CREATE TABLE UnicodeTable (str TEXT)", now; }
|
||||||
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail("recreateUnicodeTable()"); }
|
||||||
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail("recreateUnicodeTable()"); }
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CppUnit::Test* ODBCPostgreSQLTest::suite()
|
CppUnit::Test* ODBCPostgreSQLTest::suite()
|
||||||
{
|
{
|
||||||
if ((_pSession = init(_driver, _dsn, _uid, _pwd, _connectString)))
|
if ((_pSession = init(_driver, _dsn, _uid, _pwd, _connectString)))
|
||||||
@ -659,6 +674,7 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
|
|||||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTransaction);
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTransactor);
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTransactor);
|
||||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testNullable);
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testNullable);
|
||||||
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testUnicode);
|
||||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testReconnect);
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
|
@ -69,6 +69,7 @@ private:
|
|||||||
void recreateBoolTable();
|
void recreateBoolTable();
|
||||||
void recreateMiscTable();
|
void recreateMiscTable();
|
||||||
void recreateLogTable();
|
void recreateLogTable();
|
||||||
|
void recreateUnicodeTable();
|
||||||
|
|
||||||
void configurePLPgSQL();
|
void configurePLPgSQL();
|
||||||
/// Configures PL/pgSQL in the database. A reasonable defaults
|
/// Configures PL/pgSQL in the database. A reasonable defaults
|
||||||
|
@ -715,6 +715,17 @@ void ODBCSQLServerTest::recreateLogTable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ODBCSQLServerTest::recreateUnicodeTable()
|
||||||
|
{
|
||||||
|
#if defined (POCO_ODBC_UNICODE)
|
||||||
|
dropObject("TABLE", "UnicodeTable");
|
||||||
|
try { session() << "CREATE TABLE UnicodeTable (str NVARCHAR(30))", now; }
|
||||||
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail("recreateUnicodeTable()"); }
|
||||||
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail("recreateUnicodeTable()"); }
|
||||||
|
#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)))
|
||||||
@ -801,6 +812,7 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
|||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransaction);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransaction);
|
||||||
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, testReconnect);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
|
@ -74,6 +74,7 @@ private:
|
|||||||
void recreateBoolTable();
|
void recreateBoolTable();
|
||||||
void recreateMiscTable();
|
void recreateMiscTable();
|
||||||
void recreateLogTable();
|
void recreateLogTable();
|
||||||
|
void recreateUnicodeTable();
|
||||||
|
|
||||||
static SessionPtr _pSession;
|
static SessionPtr _pSession;
|
||||||
static ExecPtr _pExecutor;
|
static ExecPtr _pExecutor;
|
||||||
|
@ -969,7 +969,11 @@ void ODBCTest::testInternalBulkExtraction()
|
|||||||
recreatePersonTable();
|
recreatePersonTable();
|
||||||
_pSession->setFeature("autoBind", true);
|
_pSession->setFeature("autoBind", true);
|
||||||
_pSession->setFeature("autoExtract", true);
|
_pSession->setFeature("autoExtract", true);
|
||||||
|
#ifdef POCO_ODBC_UNICODE
|
||||||
|
_pExecutor->internalBulkExtractionUTF16();
|
||||||
|
#else
|
||||||
_pExecutor->internalBulkExtraction();
|
_pExecutor->internalBulkExtraction();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1199,6 +1203,25 @@ void ODBCTest::testNullable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ODBCTest::testUnicode()
|
||||||
|
{
|
||||||
|
#if defined (POCO_ODBC_UNICODE)
|
||||||
|
if (!_pSession) fail("Test not available.");
|
||||||
|
|
||||||
|
for (int i = 0; i < 8;)
|
||||||
|
{
|
||||||
|
recreateUnicodeTable();
|
||||||
|
_pSession->setFeature("autoBind", bindValue(i));
|
||||||
|
_pSession->setFeature("autoExtract", bindValue(i + 1));
|
||||||
|
_pExecutor->unicode(_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.");
|
||||||
@ -1296,7 +1319,7 @@ 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);
|
return new Session(Poco::Data::ODBC::Connector::KEY, dbConnString, 5);
|
||||||
}catch (ConnectionFailedException& ex)
|
}catch (ConnectionFailedException& ex)
|
||||||
{
|
{
|
||||||
std::cout << ex.displayText() << std::endl;
|
std::cout << ex.displayText() << std::endl;
|
||||||
|
@ -149,6 +149,8 @@ public:
|
|||||||
virtual void testTransactor();
|
virtual void testTransactor();
|
||||||
virtual void testNullable();
|
virtual void testNullable();
|
||||||
|
|
||||||
|
virtual void testUnicode();
|
||||||
|
|
||||||
virtual void testReconnect();
|
virtual void testReconnect();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -172,6 +174,7 @@ protected:
|
|||||||
virtual void recreateBoolTable();
|
virtual void recreateBoolTable();
|
||||||
virtual void recreateMiscTable();
|
virtual void recreateMiscTable();
|
||||||
virtual void recreateLogTable();
|
virtual void recreateLogTable();
|
||||||
|
virtual void recreateUnicodeTable();
|
||||||
|
|
||||||
static SessionPtr init(const std::string& driver,
|
static SessionPtr init(const std::string& driver,
|
||||||
std::string& dsn,
|
std::string& dsn,
|
||||||
@ -357,6 +360,12 @@ inline void ODBCTest::recreateLogTable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void ODBCTest::recreateUnicodeTable()
|
||||||
|
{
|
||||||
|
throw Poco::NotImplementedException("ODBCTest::recreateUnicodeTable()");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool ODBCTest::bindValue(int i)
|
inline bool ODBCTest::bindValue(int i)
|
||||||
{
|
{
|
||||||
poco_assert (i < 8);
|
poco_assert (i < 8);
|
||||||
|
@ -46,6 +46,8 @@
|
|||||||
#include "Poco/Data/ODBC/Preparator.h"
|
#include "Poco/Data/ODBC/Preparator.h"
|
||||||
#include "Poco/Data/ODBC/ODBCException.h"
|
#include "Poco/Data/ODBC/ODBCException.h"
|
||||||
#include "Poco/Data/ODBC/ODBCStatementImpl.h"
|
#include "Poco/Data/ODBC/ODBCStatementImpl.h"
|
||||||
|
#include "Poco/UnicodeConverter.h"
|
||||||
|
#include "Poco/UTFString.h"
|
||||||
#include <sqltypes.h>
|
#include <sqltypes.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -94,7 +96,9 @@ using Poco::NotImplementedException;
|
|||||||
using Poco::BadCastException;
|
using Poco::BadCastException;
|
||||||
using Poco::RangeException;
|
using Poco::RangeException;
|
||||||
using Poco::TimeoutException;
|
using Poco::TimeoutException;
|
||||||
|
using Poco::UnicodeConverter;
|
||||||
|
using Poco::UTF16String;
|
||||||
|
using Poco::UTF32String;
|
||||||
|
|
||||||
struct Person
|
struct Person
|
||||||
{
|
{
|
||||||
@ -2441,24 +2445,24 @@ void SQLExecutor::dateTime()
|
|||||||
DateTime born(1965, 6, 18, 5, 35, 1);
|
DateTime born(1965, 6, 18, 5, 35, 1);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(born), now; }
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(born), now; }
|
||||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
||||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
||||||
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
||||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
||||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
||||||
assert (count == 1);
|
assert(count == 1);
|
||||||
|
|
||||||
DateTime res;
|
DateTime res;
|
||||||
try { session() << "SELECT Born FROM Person", into(res), now; }
|
try { session() << "SELECT Born FROM Person", into(res), now; }
|
||||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
||||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
||||||
assert (res == born);
|
assert(res == born);
|
||||||
|
|
||||||
Statement stmt = (session() << "SELECT Born FROM Person", now);
|
Statement stmt = (session() << "SELECT Born FROM Person", now);
|
||||||
RecordSet rset(stmt);
|
RecordSet rset(stmt);
|
||||||
|
|
||||||
res = rset["Born"].convert<DateTime>();
|
res = rset["Born"].convert<DateTime>();
|
||||||
assert (res == born);
|
assert(res == born);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2619,7 +2623,7 @@ void SQLExecutor::internalExtraction()
|
|||||||
rset.moveFirst();
|
rset.moveFirst();
|
||||||
assert (rset["str0"] == "3");
|
assert (rset["str0"] == "3");
|
||||||
rset.moveLast();
|
rset.moveLast();
|
||||||
assert (rset["str0"] == "6");
|
assert(rset["str0"] == "6");
|
||||||
|
|
||||||
RecordSet rset2(rset);
|
RecordSet rset2(rset);
|
||||||
assert (3 == rset2.columnCount());
|
assert (3 == rset2.columnCount());
|
||||||
@ -2645,8 +2649,17 @@ void SQLExecutor::internalExtraction()
|
|||||||
assert (2.5 == f);
|
assert (2.5 == f);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = rset.value<std::string>(2,2);
|
try
|
||||||
assert ("5" == s);
|
{
|
||||||
|
s = rset.value<std::string>(2, 2);
|
||||||
|
}
|
||||||
|
catch (BadCastException&)
|
||||||
|
{
|
||||||
|
UTF16String us = rset.value<Poco::UTF16String>(2, 2);
|
||||||
|
Poco::UnicodeConverter::convert(us, s);
|
||||||
|
}
|
||||||
|
assert("5" == s);
|
||||||
|
|
||||||
i = rset.value("str0", 2);
|
i = rset.value("str0", 2);
|
||||||
assert (5 == i);
|
assert (5 == i);
|
||||||
|
|
||||||
@ -2815,8 +2828,11 @@ void SQLExecutor::internalBulkExtraction()
|
|||||||
Statement stmt = (session() << "SELECT * FROM Person", bulk(size), now);
|
Statement stmt = (session() << "SELECT * FROM Person", bulk(size), now);
|
||||||
RecordSet rset(stmt);
|
RecordSet rset(stmt);
|
||||||
assert (size == rset.rowCount());
|
assert (size == rset.rowCount());
|
||||||
assert ("LN0" == rset["LastName"]);
|
assert("LN0" == rset["LastName"]);
|
||||||
assert (0 == rset["Age"]);
|
assert (0 == rset["Age"]);
|
||||||
|
rset.moveNext();
|
||||||
|
assert("LN1" == rset["LastName"]);
|
||||||
|
assert(1 == rset["Age"]);
|
||||||
rset.moveLast();
|
rset.moveLast();
|
||||||
assert (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]);
|
assert (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]);
|
||||||
assert (size - 1 == rset["Age"]);
|
assert (size - 1 == rset["Age"]);
|
||||||
@ -2840,6 +2856,68 @@ void SQLExecutor::internalBulkExtraction()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SQLExecutor::internalBulkExtractionUTF16()
|
||||||
|
{
|
||||||
|
std::string funct = "internalBulkExtraction()";
|
||||||
|
int size = 100;
|
||||||
|
std::vector<UTF16String> lastName(size);
|
||||||
|
std::vector<UTF16String> firstName(size);
|
||||||
|
std::vector<UTF16String> address(size);
|
||||||
|
std::vector<int> age(size);
|
||||||
|
|
||||||
|
for (int i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
lastName[i] = Poco::UnicodeConverter::to<UTF16String>("LN" + NumberFormatter::format(i));
|
||||||
|
firstName[i] = Poco::UnicodeConverter::to<UTF16String>("FN" + NumberFormatter::format(i));
|
||||||
|
address[i] = Poco::UnicodeConverter::to<UTF16String>("Addr" + NumberFormatter::format(i));
|
||||||
|
age[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
session() << "INSERT INTO Person VALUES (?,?,?,?)",
|
||||||
|
use(lastName, bulk),
|
||||||
|
use(firstName, bulk),
|
||||||
|
use(address, bulk),
|
||||||
|
use(age, bulk),
|
||||||
|
now;
|
||||||
|
}
|
||||||
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
||||||
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Statement stmt = (session() << "SELECT * FROM Person", bulk(size), now);
|
||||||
|
RecordSet rset(stmt);
|
||||||
|
assert(size == rset.rowCount());
|
||||||
|
assert(Poco::UnicodeConverter::to<UTF16String>("LN0") == rset["LastName"]);
|
||||||
|
assert(0 == rset["Age"]);
|
||||||
|
rset.moveNext();
|
||||||
|
assert(Poco::UnicodeConverter::to<UTF16String>("LN1") == rset["LastName"]);
|
||||||
|
assert(1 == rset["Age"]);
|
||||||
|
rset.moveLast();
|
||||||
|
assert(std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]);
|
||||||
|
assert(size - 1 == rset["Age"]);
|
||||||
|
}
|
||||||
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
||||||
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Statement stmt = (session() << "SELECT * FROM Person", limit(size), bulk, now);
|
||||||
|
RecordSet rset(stmt);
|
||||||
|
assert(size == rset.rowCount());
|
||||||
|
assert("LN0" == rset["LastName"]);
|
||||||
|
assert(0 == rset["Age"]);
|
||||||
|
rset.moveLast();
|
||||||
|
assert(std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]);
|
||||||
|
assert(size - 1 == rset["Age"]);
|
||||||
|
}
|
||||||
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
||||||
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SQLExecutor::internalStorageType()
|
void SQLExecutor::internalStorageType()
|
||||||
{
|
{
|
||||||
std::string funct = "internalStorageType()";
|
std::string funct = "internalStorageType()";
|
||||||
@ -3247,8 +3325,13 @@ void SQLExecutor::any()
|
|||||||
{
|
{
|
||||||
Any i = 42;
|
Any i = 42;
|
||||||
Any f = 42.5;
|
Any f = 42.5;
|
||||||
Any s = std::string("42");
|
std::string ss("42");
|
||||||
|
Any s = ss;
|
||||||
|
#ifdef POCO_ODBC_UNICODE
|
||||||
|
UTF16String us;
|
||||||
|
Poco::UnicodeConverter::convert(ss, us);
|
||||||
|
s = us;
|
||||||
|
#endif
|
||||||
Session tmp = session();
|
Session tmp = session();
|
||||||
|
|
||||||
tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now;
|
tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now;
|
||||||
@ -3263,7 +3346,19 @@ void SQLExecutor::any()
|
|||||||
tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now;
|
tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now;
|
||||||
assert (AnyCast<int>(i) == 42);
|
assert (AnyCast<int>(i) == 42);
|
||||||
assert (AnyCast<double>(f) == 42.5);
|
assert (AnyCast<double>(f) == 42.5);
|
||||||
|
#ifdef POCO_ODBC_UNICODE
|
||||||
|
// drivers may behave differently here
|
||||||
|
try
|
||||||
|
{
|
||||||
|
assert(AnyCast<UTF16String>(s) == us);
|
||||||
|
}
|
||||||
|
catch (BadCastException&)
|
||||||
|
{
|
||||||
|
assert (AnyCast<std::string>(s) == "42");
|
||||||
|
}
|
||||||
|
#else
|
||||||
assert (AnyCast<std::string>(s) == "42");
|
assert (AnyCast<std::string>(s) == "42");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3830,7 +3925,7 @@ void SQLExecutor::nullable()
|
|||||||
assert (rs.isNull("EmptyInteger"));
|
assert (rs.isNull("EmptyInteger"));
|
||||||
assert (rs.isNull("EmptyFloat"));
|
assert (rs.isNull("EmptyFloat"));
|
||||||
assert (rs.isNull("EmptyDateTime"));
|
assert (rs.isNull("EmptyDateTime"));
|
||||||
|
|
||||||
Var di = 1;
|
Var di = 1;
|
||||||
Var df = 1.5;
|
Var df = 1.5;
|
||||||
Var ds = "abc";
|
Var ds = "abc";
|
||||||
@ -3840,8 +3935,8 @@ void SQLExecutor::nullable()
|
|||||||
assert (!df.isEmpty());
|
assert (!df.isEmpty());
|
||||||
assert (!ds.isEmpty());
|
assert (!ds.isEmpty());
|
||||||
assert (!dd.isEmpty());
|
assert (!dd.isEmpty());
|
||||||
|
|
||||||
session() << "SELECT EmptyString, EmptyInteger, EmptyFloat, EmptyDateTime FROM NullableTest", into(di), into(df), into(ds), into(dd), now;
|
Statement stmt = (session() << "SELECT EmptyString, EmptyInteger, EmptyFloat, EmptyDateTime FROM NullableTest", into(ds), into(di), into(df), into(dd), now);
|
||||||
|
|
||||||
assert (di.isEmpty());
|
assert (di.isEmpty());
|
||||||
assert (df.isEmpty());
|
assert (df.isEmpty());
|
||||||
@ -3889,3 +3984,19 @@ void SQLExecutor::reconnect()
|
|||||||
assert (count == age);
|
assert (count == age);
|
||||||
assert (session().isConnected());
|
assert (session().isConnected());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SQLExecutor::unicode(const std::string& dbConnString)
|
||||||
|
{
|
||||||
|
const unsigned char supp[] = { 0x41, 0x42, 0xf0, 0x90, 0x82, 0xa4, 0xf0, 0xaf, 0xa6, 0xa0, 0xf0, 0xaf, 0xa8, 0x9d, 0x00 };
|
||||||
|
std::string text((const char*) supp);
|
||||||
|
|
||||||
|
UTF16String wtext;
|
||||||
|
Poco::UnicodeConverter::convert(text, wtext);
|
||||||
|
session() << "INSERT INTO UnicodeTable VALUES (?)", use(wtext), now;
|
||||||
|
wtext.clear();
|
||||||
|
text.clear();
|
||||||
|
session() << "SELECT str FROM UnicodeTable", into(wtext), now;
|
||||||
|
Poco::UnicodeConverter::convert(wtext, text);
|
||||||
|
assert(text == std::string((const char*)supp));
|
||||||
|
}
|
@ -479,6 +479,7 @@ public:
|
|||||||
const std::string& intFldName = "int0");
|
const std::string& intFldName = "int0");
|
||||||
|
|
||||||
void internalBulkExtraction();
|
void internalBulkExtraction();
|
||||||
|
void internalBulkExtractionUTF16();
|
||||||
void internalStorageType();
|
void internalStorageType();
|
||||||
void nulls();
|
void nulls();
|
||||||
void notNulls(const std::string& sqlState = "23502");
|
void notNulls(const std::string& sqlState = "23502");
|
||||||
@ -503,6 +504,8 @@ public:
|
|||||||
void transactor();
|
void transactor();
|
||||||
void nullable();
|
void nullable();
|
||||||
|
|
||||||
|
void unicode(const std::string& dbConnString);
|
||||||
|
|
||||||
void reconnect();
|
void reconnect();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "Poco/Nullable.h"
|
#include "Poco/Nullable.h"
|
||||||
#include "Poco/Any.h"
|
#include "Poco/Any.h"
|
||||||
#include "Poco/Dynamic/Var.h"
|
#include "Poco/Dynamic/Var.h"
|
||||||
|
#include "Poco/UTFString.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -246,6 +247,18 @@ public:
|
|||||||
virtual void bind(std::size_t pos, const std::list<std::string>& val, Direction dir = PD_IN);
|
virtual void bind(std::size_t pos, const std::list<std::string>& val, Direction dir = PD_IN);
|
||||||
/// Binds a string list.
|
/// Binds a string list.
|
||||||
|
|
||||||
|
virtual void bind(std::size_t pos, const UTF16String& val, Direction dir = PD_IN) = 0;
|
||||||
|
/// Binds a string.
|
||||||
|
|
||||||
|
virtual void bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir = PD_IN);
|
||||||
|
/// Binds a string vector.
|
||||||
|
|
||||||
|
virtual void bind(std::size_t pos, const std::deque<UTF16String>& val, Direction dir = PD_IN);
|
||||||
|
/// Binds a string deque.
|
||||||
|
|
||||||
|
virtual void bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir = PD_IN);
|
||||||
|
/// Binds a string list.
|
||||||
|
|
||||||
virtual void bind(std::size_t pos, const BLOB& val, Direction dir = PD_IN) = 0;
|
virtual void bind(std::size_t pos, const BLOB& val, Direction dir = PD_IN) = 0;
|
||||||
/// Binds a BLOB.
|
/// Binds a BLOB.
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "Poco/Data/AbstractPreparation.h"
|
#include "Poco/Data/AbstractPreparation.h"
|
||||||
#include "Poco/Data/Limit.h"
|
#include "Poco/Data/Limit.h"
|
||||||
#include "Poco/RefCountedObject.h"
|
#include "Poco/RefCountedObject.h"
|
||||||
|
#include "Poco/UTFString.h"
|
||||||
#include "Poco/AutoPtr.h"
|
#include "Poco/AutoPtr.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
@ -144,7 +145,26 @@ public:
|
|||||||
/// - string is empty
|
/// - string is empty
|
||||||
/// - getEmptyStringIsNull() returns true
|
/// - getEmptyStringIsNull() returns true
|
||||||
|
|
||||||
|
bool isValueNull(const Poco::UTF16String& str, bool deflt);
|
||||||
|
/// Overload for const reference to UTF16String.
|
||||||
|
///
|
||||||
|
/// Returns true when folowing conditions are met:
|
||||||
|
///
|
||||||
|
/// - string is empty
|
||||||
|
/// - getEmptyStringIsNull() returns true
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template <typename S>
|
||||||
|
bool isStringNull(const S& str, bool deflt)
|
||||||
|
{
|
||||||
|
if (getForceEmptyString()) return false;
|
||||||
|
|
||||||
|
if (getEmptyStringIsNull() && str.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return deflt;
|
||||||
|
}
|
||||||
|
|
||||||
ExtractorPtr _pExtractor;
|
ExtractorPtr _pExtractor;
|
||||||
Poco::UInt32 _limit;
|
Poco::UInt32 _limit;
|
||||||
Poco::UInt32 _position;
|
Poco::UInt32 _position;
|
||||||
@ -242,6 +262,18 @@ inline bool AbstractExtraction::getForceEmptyString() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool AbstractExtraction::isValueNull(const std::string& str, bool deflt)
|
||||||
|
{
|
||||||
|
return isStringNull(str, deflt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool AbstractExtraction::isValueNull(const Poco::UTF16String& str, bool deflt)
|
||||||
|
{
|
||||||
|
return isStringNull(str, deflt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "Poco/Data/Data.h"
|
#include "Poco/Data/Data.h"
|
||||||
#include "Poco/Data/Constants.h"
|
#include "Poco/Data/Constants.h"
|
||||||
#include "Poco/Data/LOB.h"
|
#include "Poco/Data/LOB.h"
|
||||||
|
#include "Poco/UTFString.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -233,6 +234,18 @@ public:
|
|||||||
virtual bool extract(std::size_t pos, std::list<std::string>& val);
|
virtual bool extract(std::size_t pos, std::list<std::string>& val);
|
||||||
/// Extracts a string list.
|
/// Extracts a string list.
|
||||||
|
|
||||||
|
virtual bool extract(std::size_t pos, UTF16String& val) = 0;
|
||||||
|
/// Extracts a string. Returns false if null was received.
|
||||||
|
|
||||||
|
virtual bool extract(std::size_t pos, std::vector<UTF16String>& val);
|
||||||
|
/// Extracts a string vector.
|
||||||
|
|
||||||
|
virtual bool extract(std::size_t pos, std::deque<UTF16String>& val);
|
||||||
|
/// Extracts a string deque.
|
||||||
|
|
||||||
|
virtual bool extract(std::size_t pos, std::list<UTF16String>& val);
|
||||||
|
/// Extracts a string list.
|
||||||
|
|
||||||
virtual bool extract(std::size_t pos, BLOB& val) = 0;
|
virtual bool extract(std::size_t pos, BLOB& val) = 0;
|
||||||
/// Extracts a BLOB. Returns false if null was received.
|
/// Extracts a BLOB. Returns false if null was received.
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ public:
|
|||||||
/// Destroys the AbstractPreparation.
|
/// Destroys the AbstractPreparation.
|
||||||
|
|
||||||
virtual void prepare() = 0;
|
virtual void prepare() = 0;
|
||||||
/// Preparations data.
|
/// Prepares data.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AbstractPreparation();
|
AbstractPreparation();
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "Poco/Data/Data.h"
|
#include "Poco/Data/Data.h"
|
||||||
#include "Poco/RefCountedObject.h"
|
#include "Poco/RefCountedObject.h"
|
||||||
#include "Poco/Data/LOB.h"
|
#include "Poco/Data/LOB.h"
|
||||||
|
#include "Poco/UTFString.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -237,6 +238,18 @@ public:
|
|||||||
/// Prepares a string deque.
|
/// Prepares a string deque.
|
||||||
|
|
||||||
virtual void prepare(std::size_t pos, const std::list<std::string>& val);
|
virtual void prepare(std::size_t pos, const std::list<std::string>& val);
|
||||||
|
/// Prepares a character list.
|
||||||
|
|
||||||
|
virtual void prepare(std::size_t pos, const UTF16String&) = 0;
|
||||||
|
/// Prepares a string.
|
||||||
|
|
||||||
|
virtual void prepare(std::size_t pos, const std::vector<UTF16String>& val);
|
||||||
|
/// Prepares a string vector.
|
||||||
|
|
||||||
|
virtual void prepare(std::size_t pos, const std::deque<UTF16String>& val);
|
||||||
|
/// Prepares a string deque.
|
||||||
|
|
||||||
|
virtual void prepare(std::size_t pos, const std::list<UTF16String>& val);
|
||||||
/// Prepares a string list.
|
/// Prepares a string list.
|
||||||
|
|
||||||
virtual void prepare(std::size_t pos, const BLOB&) = 0;
|
virtual void prepare(std::size_t pos, const BLOB&) = 0;
|
||||||
|
@ -46,6 +46,7 @@ public:
|
|||||||
FDT_FLOAT,
|
FDT_FLOAT,
|
||||||
FDT_DOUBLE,
|
FDT_DOUBLE,
|
||||||
FDT_STRING,
|
FDT_STRING,
|
||||||
|
FDT_WSTRING,
|
||||||
FDT_BLOB,
|
FDT_BLOB,
|
||||||
FDT_CLOB,
|
FDT_CLOB,
|
||||||
FDT_DATE,
|
FDT_DATE,
|
||||||
|
@ -50,7 +50,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void prepare()
|
void prepare()
|
||||||
/// Preparations data.
|
/// Prepares data.
|
||||||
{
|
{
|
||||||
TypeHandler<T>::prepare(_pos, _val, preparation());
|
TypeHandler<T>::prepare(_pos, _val, preparation());
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void prepare()
|
void prepare()
|
||||||
/// Preparations data.
|
/// Prepares data.
|
||||||
{
|
{
|
||||||
TypeHandler<std::vector<T> >::prepare(_pos, _val, preparation());
|
TypeHandler<std::vector<T> >::prepare(_pos, _val, preparation());
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void prepare()
|
void prepare()
|
||||||
/// Preparations data.
|
/// Prepares data.
|
||||||
{
|
{
|
||||||
TypeHandler<std::deque<T> >::prepare(_pos, _val, preparation());
|
TypeHandler<std::deque<T> >::prepare(_pos, _val, preparation());
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void prepare()
|
void prepare()
|
||||||
/// Preparations data.
|
/// Prepares data.
|
||||||
{
|
{
|
||||||
TypeHandler<std::list<T> >::prepare(_pos, _val, preparation());
|
TypeHandler<std::list<T> >::prepare(_pos, _val, preparation());
|
||||||
}
|
}
|
||||||
|
@ -292,6 +292,24 @@ void AbstractBinder::bind(std::size_t pos, const std::list<std::string>& val, Di
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractBinder::bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir)
|
||||||
|
{
|
||||||
|
throw NotImplementedException("std::vector binder must be implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractBinder::bind(std::size_t pos, const std::deque<UTF16String>& val, Direction dir)
|
||||||
|
{
|
||||||
|
throw NotImplementedException("std::deque binder must be implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractBinder::bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir)
|
||||||
|
{
|
||||||
|
throw NotImplementedException("std::list binder must be implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AbstractBinder::bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir)
|
void AbstractBinder::bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir)
|
||||||
{
|
{
|
||||||
throw NotImplementedException("std::vector binder must be implemented.");
|
throw NotImplementedException("std::vector binder must be implemented.");
|
||||||
@ -408,6 +426,8 @@ void AbstractBinder::bind(std::size_t pos, const Any& val, Direction dir)
|
|||||||
bind(pos, RefAnyCast<Int32>(val), dir);
|
bind(pos, RefAnyCast<Int32>(val), dir);
|
||||||
else if(type == typeid(std::string))
|
else if(type == typeid(std::string))
|
||||||
bind(pos, RefAnyCast<std::string>(val), dir);
|
bind(pos, RefAnyCast<std::string>(val), dir);
|
||||||
|
else if (type == typeid(Poco::UTF16String))
|
||||||
|
bind(pos, RefAnyCast<Poco::UTF16String>(val), dir);
|
||||||
else if (type == typeid(bool))
|
else if (type == typeid(bool))
|
||||||
bind(pos, RefAnyCast<bool>(val), dir);
|
bind(pos, RefAnyCast<bool>(val), dir);
|
||||||
else if(type == typeid(char))
|
else if(type == typeid(char))
|
||||||
@ -457,6 +477,8 @@ void AbstractBinder::bind(std::size_t pos, const Poco::Dynamic::Var& val, Direct
|
|||||||
bind(pos, val.extract<Int32>(), dir);
|
bind(pos, val.extract<Int32>(), dir);
|
||||||
else if(type == typeid(std::string))
|
else if(type == typeid(std::string))
|
||||||
bind(pos, val.extract<std::string>(), dir);
|
bind(pos, val.extract<std::string>(), dir);
|
||||||
|
else if (type == typeid(Poco::UTF16String))
|
||||||
|
bind(pos, val.extract<Poco::UTF16String>(), dir);
|
||||||
else if (type == typeid(bool))
|
else if (type == typeid(bool))
|
||||||
bind(pos, val.extract<bool>(), dir);
|
bind(pos, val.extract<bool>(), dir);
|
||||||
else if(type == typeid(char))
|
else if(type == typeid(char))
|
||||||
|
@ -39,15 +39,4 @@ AbstractExtraction::~AbstractExtraction()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AbstractExtraction::isValueNull(const std::string& str, bool deflt)
|
|
||||||
{
|
|
||||||
if (getForceEmptyString()) return false;
|
|
||||||
|
|
||||||
if (getEmptyStringIsNull() && str.empty())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return deflt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
@ -286,6 +286,24 @@ bool AbstractExtractor::extract(std::size_t pos, std::list<std::string>& val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool AbstractExtractor::extract(std::size_t pos, std::vector<UTF16String>& val)
|
||||||
|
{
|
||||||
|
throw NotImplementedException("std::vector extractor must be implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool AbstractExtractor::extract(std::size_t pos, std::deque<UTF16String>& val)
|
||||||
|
{
|
||||||
|
throw NotImplementedException("std::deque extractor must be implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool AbstractExtractor::extract(std::size_t pos, std::list<UTF16String>& val)
|
||||||
|
{
|
||||||
|
throw NotImplementedException("std::list extractor must be implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AbstractExtractor::extract(std::size_t pos, std::vector<BLOB>& val)
|
bool AbstractExtractor::extract(std::size_t pos, std::vector<BLOB>& val)
|
||||||
{
|
{
|
||||||
throw NotImplementedException("std::vector extractor must be implemented.");
|
throw NotImplementedException("std::vector extractor must be implemented.");
|
||||||
|
@ -287,6 +287,24 @@ void AbstractPreparator::prepare(std::size_t pos, const std::list<std::string>&
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractPreparator::prepare(std::size_t pos, const std::vector<UTF16String>& val)
|
||||||
|
{
|
||||||
|
throw NotImplementedException("std::vector preparator must be implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractPreparator::prepare(std::size_t pos, const std::deque<UTF16String>& val)
|
||||||
|
{
|
||||||
|
throw NotImplementedException("std::deque preparator must be implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractPreparator::prepare(std::size_t pos, const std::list<UTF16String>& val)
|
||||||
|
{
|
||||||
|
throw NotImplementedException("std::list preparator must be implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AbstractPreparator::prepare(std::size_t pos, const std::vector<BLOB>& val)
|
void AbstractPreparator::prepare(std::size_t pos, const std::vector<BLOB>& val)
|
||||||
{
|
{
|
||||||
throw NotImplementedException("std::vector preparator must be implemented.");
|
throw NotImplementedException("std::vector preparator must be implemented.");
|
||||||
|
@ -20,10 +20,12 @@
|
|||||||
#include "Poco/Data/Time.h"
|
#include "Poco/Data/Time.h"
|
||||||
#include "Poco/Data/DataException.h"
|
#include "Poco/Data/DataException.h"
|
||||||
#include "Poco/DateTime.h"
|
#include "Poco/DateTime.h"
|
||||||
|
#include "Poco/UTFString.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace Poco::Data::Keywords;
|
using namespace Poco::Data::Keywords;
|
||||||
using Poco::DateTime;
|
using Poco::DateTime;
|
||||||
|
using Poco::UTF16String;
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@ -104,6 +106,7 @@ Poco::Dynamic::Var RecordSet::value(std::size_t col, std::size_t row, bool useFi
|
|||||||
case MetaColumn::FDT_FLOAT: return value<float>(col, row, useFilter);
|
case MetaColumn::FDT_FLOAT: return value<float>(col, row, useFilter);
|
||||||
case MetaColumn::FDT_DOUBLE: return value<double>(col, row, useFilter);
|
case MetaColumn::FDT_DOUBLE: return value<double>(col, row, useFilter);
|
||||||
case MetaColumn::FDT_STRING: return value<std::string>(col, row, useFilter);
|
case MetaColumn::FDT_STRING: return value<std::string>(col, row, useFilter);
|
||||||
|
case MetaColumn::FDT_WSTRING: return value<UTF16String>(col, row, useFilter);
|
||||||
case MetaColumn::FDT_BLOB: return value<BLOB>(col, row, useFilter);
|
case MetaColumn::FDT_BLOB: return value<BLOB>(col, row, useFilter);
|
||||||
case MetaColumn::FDT_CLOB: return value<CLOB>(col, row, useFilter);
|
case MetaColumn::FDT_CLOB: return value<CLOB>(col, row, useFilter);
|
||||||
case MetaColumn::FDT_DATE: return value<Date>(col, row, useFilter);
|
case MetaColumn::FDT_DATE: return value<Date>(col, row, useFilter);
|
||||||
@ -136,6 +139,7 @@ Poco::Dynamic::Var RecordSet::value(const std::string& name, std::size_t row, bo
|
|||||||
case MetaColumn::FDT_FLOAT: return value<float>(name, row, useFilter);
|
case MetaColumn::FDT_FLOAT: return value<float>(name, row, useFilter);
|
||||||
case MetaColumn::FDT_DOUBLE: return value<double>(name, row, useFilter);
|
case MetaColumn::FDT_DOUBLE: return value<double>(name, row, useFilter);
|
||||||
case MetaColumn::FDT_STRING: return value<std::string>(name, row, useFilter);
|
case MetaColumn::FDT_STRING: return value<std::string>(name, row, useFilter);
|
||||||
|
case MetaColumn::FDT_WSTRING: return value<UTF16String>(name, row, useFilter);
|
||||||
case MetaColumn::FDT_BLOB: return value<BLOB>(name, row, useFilter);
|
case MetaColumn::FDT_BLOB: return value<BLOB>(name, row, useFilter);
|
||||||
case MetaColumn::FDT_DATE: return value<Date>(name, row, useFilter);
|
case MetaColumn::FDT_DATE: return value<Date>(name, row, useFilter);
|
||||||
case MetaColumn::FDT_TIME: return value<Time>(name, row, useFilter);
|
case MetaColumn::FDT_TIME: return value<Time>(name, row, useFilter);
|
||||||
|
@ -327,6 +327,8 @@ void StatementImpl::makeExtractors(std::size_t count)
|
|||||||
addInternalExtract<double>(mc); break;
|
addInternalExtract<double>(mc); break;
|
||||||
case MetaColumn::FDT_STRING:
|
case MetaColumn::FDT_STRING:
|
||||||
addInternalExtract<std::string>(mc); break;
|
addInternalExtract<std::string>(mc); break;
|
||||||
|
case MetaColumn::FDT_WSTRING:
|
||||||
|
addInternalExtract<Poco::UTF16String>(mc); break;
|
||||||
case MetaColumn::FDT_BLOB:
|
case MetaColumn::FDT_BLOB:
|
||||||
addInternalExtract<BLOB>(mc); break;
|
addInternalExtract<BLOB>(mc); break;
|
||||||
case MetaColumn::FDT_DATE:
|
case MetaColumn::FDT_DATE:
|
||||||
|
@ -112,6 +112,11 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Binder::bind(std::size_t pos, const Poco::UTF16String& val, Direction dir)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Binder::bind(std::size_t pos, const BLOB& val, Direction dir)
|
void Binder::bind(std::size_t pos, const BLOB& val, Direction dir)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,9 @@ public:
|
|||||||
void bind(std::size_t pos, const std::string& val, Direction dir);
|
void bind(std::size_t pos, const std::string& val, Direction dir);
|
||||||
/// Binds a string.
|
/// Binds a string.
|
||||||
|
|
||||||
|
void bind(std::size_t pos, const Poco::UTF16String& val, Direction dir);
|
||||||
|
/// Binds a UTF16String.
|
||||||
|
|
||||||
void bind(std::size_t pos, const BLOB& val, Direction dir);
|
void bind(std::size_t pos, const BLOB& val, Direction dir);
|
||||||
/// Binds a BLOB.
|
/// Binds a BLOB.
|
||||||
|
|
||||||
|
@ -137,6 +137,14 @@ bool Extractor::extract(std::size_t pos, std::string& val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Extractor::extract(std::size_t pos, Poco::UTF16String& val)
|
||||||
|
{
|
||||||
|
std::string str("");
|
||||||
|
Poco::UnicodeConverter::convert(str, val);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
|
bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -87,6 +87,9 @@ public:
|
|||||||
bool extract(std::size_t pos, std::string& val);
|
bool extract(std::size_t pos, std::string& val);
|
||||||
/// Extracts a string.
|
/// Extracts a string.
|
||||||
|
|
||||||
|
bool extract(std::size_t pos, Poco::UTF16String& val);
|
||||||
|
/// Extracts a UTF16String.
|
||||||
|
|
||||||
bool extract(std::size_t pos, Poco::Data::BLOB& val);
|
bool extract(std::size_t pos, Poco::Data::BLOB& val);
|
||||||
/// Extracts a BLOB.
|
/// Extracts a BLOB.
|
||||||
|
|
||||||
|
@ -107,6 +107,11 @@ void Preparator::prepare(std::size_t pos, const std::string&)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Preparator::prepare(std::size_t pos, const Poco::UTF16String&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Preparator::prepare(std::size_t pos, const Poco::Data::BLOB&)
|
void Preparator::prepare(std::size_t pos, const Poco::Data::BLOB&)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -36,72 +36,75 @@ public:
|
|||||||
/// Destroys the Preparator.
|
/// Destroys the Preparator.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::Int8&);
|
void prepare(std::size_t pos, const Poco::Int8&);
|
||||||
/// Preparations an Int8.
|
/// Prepares an Int8.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::UInt8&);
|
void prepare(std::size_t pos, const Poco::UInt8&);
|
||||||
/// Preparations an UInt8.
|
/// Prepares an UInt8.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::Int16&);
|
void prepare(std::size_t pos, const Poco::Int16&);
|
||||||
/// Preparations an Int16.
|
/// Prepares an Int16.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::UInt16&);
|
void prepare(std::size_t pos, const Poco::UInt16&);
|
||||||
/// Preparations an UInt16.
|
/// Prepares an UInt16.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::Int32&);
|
void prepare(std::size_t pos, const Poco::Int32&);
|
||||||
/// Preparations an Int32.
|
/// Prepares an Int32.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::UInt32&);
|
void prepare(std::size_t pos, const Poco::UInt32&);
|
||||||
/// Preparations an UInt32.
|
/// Prepares an UInt32.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::Int64&);
|
void prepare(std::size_t pos, const Poco::Int64&);
|
||||||
/// Preparations an Int64.
|
/// Prepares an Int64.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::UInt64&);
|
void prepare(std::size_t pos, const Poco::UInt64&);
|
||||||
/// Preparations an UInt64.
|
/// Prepares an UInt64.
|
||||||
|
|
||||||
#ifndef POCO_LONG_IS_64_BIT
|
#ifndef POCO_LONG_IS_64_BIT
|
||||||
void prepare(std::size_t pos, const long&);
|
void prepare(std::size_t pos, const long&);
|
||||||
/// Preparations a long.
|
/// Prepares a long.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const unsigned long&);
|
void prepare(std::size_t pos, const unsigned long&);
|
||||||
/// Preparations an unsigned long.
|
/// Prepares an unsigned long.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void prepare(std::size_t pos, const bool&);
|
void prepare(std::size_t pos, const bool&);
|
||||||
/// Preparations a boolean.
|
/// Prepares a boolean.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const float&);
|
void prepare(std::size_t pos, const float&);
|
||||||
/// Preparations a float.
|
/// Prepares a float.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const double&);
|
void prepare(std::size_t pos, const double&);
|
||||||
/// Preparations a double.
|
/// Prepares a double.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const char&);
|
void prepare(std::size_t pos, const char&);
|
||||||
/// Preparations a single character.
|
/// Prepares a single character.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const std::string&);
|
void prepare(std::size_t pos, const std::string&);
|
||||||
/// Preparations a string.
|
/// Prepares a string.
|
||||||
|
|
||||||
|
void prepare(std::size_t pos, const Poco::UTF16String&);
|
||||||
|
/// Prepares a UTF16String.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::Data::BLOB&);
|
void prepare(std::size_t pos, const Poco::Data::BLOB&);
|
||||||
/// Preparations a BLOB.
|
/// Prepares a BLOB.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::Data::CLOB&);
|
void prepare(std::size_t pos, const Poco::Data::CLOB&);
|
||||||
/// Preparations a CLOB.
|
/// Prepares a CLOB.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::Data::Date&);
|
void prepare(std::size_t pos, const Poco::Data::Date&);
|
||||||
/// Preparations a Date.
|
/// Prepares a Date.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::Data::Time&);
|
void prepare(std::size_t pos, const Poco::Data::Time&);
|
||||||
/// Preparations a Time.
|
/// Prepares a Time.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::DateTime&);
|
void prepare(std::size_t pos, const Poco::DateTime&);
|
||||||
/// Preparations a DateTime.
|
/// Prepares a DateTime.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::Any&);
|
void prepare(std::size_t pos, const Poco::Any&);
|
||||||
/// Preparations an Any.
|
/// Prepares an Any.
|
||||||
|
|
||||||
void prepare(std::size_t pos, const Poco::Dynamic::Var&);
|
void prepare(std::size_t pos, const Poco::Dynamic::Var&);
|
||||||
/// Preparations a Var.
|
/// Prepares a Var.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1060,6 +1060,7 @@
|
|||||||
<ClInclude Include="include\Poco\Types.h" />
|
<ClInclude Include="include\Poco\Types.h" />
|
||||||
<ClInclude Include="include\Poco\UnWindows.h" />
|
<ClInclude Include="include\Poco\UnWindows.h" />
|
||||||
<ClInclude Include="include\Poco\UTF32Encoding.h" />
|
<ClInclude Include="include\Poco\UTF32Encoding.h" />
|
||||||
|
<ClInclude Include="include\Poco\UTFString.h" />
|
||||||
<ClInclude Include="include\Poco\Version.h" />
|
<ClInclude Include="include\Poco\Version.h" />
|
||||||
<ClInclude Include="include\Poco\Void.h" />
|
<ClInclude Include="include\Poco\Void.h" />
|
||||||
<ClInclude Include="include\Poco\Base32Decoder.h" />
|
<ClInclude Include="include\Poco\Base32Decoder.h" />
|
||||||
|
@ -1880,6 +1880,10 @@
|
|||||||
<ClInclude Include="include\Poco\UTF32Encoding.h">
|
<ClInclude Include="include\Poco\UTF32Encoding.h">
|
||||||
<Filter>Text\Header Files</Filter>
|
<Filter>Text\Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\Poco\PBKDF2Engine.h" />
|
||||||
|
<ClInclude Include="include\Poco\UTFString.h">
|
||||||
|
<Filter>Text\Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="src\pocomsg.rc">
|
<ResourceCompile Include="src\pocomsg.rc">
|
||||||
|
@ -2027,6 +2027,22 @@ inline bool operator != (const std::string& other, const Var& da)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool operator == (const UTF16String& other, const Var& da)
|
||||||
|
/// Equality operator for comparing Var with UTF16String
|
||||||
|
{
|
||||||
|
if (da.isEmpty()) return false;
|
||||||
|
return other == da.convert<UTF16String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool operator != (const UTF16String& other, const Var& da)
|
||||||
|
/// Inequality operator for comparing Var with UTF16String
|
||||||
|
{
|
||||||
|
if (da.isEmpty()) return true;
|
||||||
|
return other != da.convert<UTF16String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool operator == (const char* other, const Var& da)
|
inline bool operator == (const char* other, const Var& da)
|
||||||
/// Equality operator for comparing Var with const char*
|
/// Equality operator for comparing Var with const char*
|
||||||
{
|
{
|
||||||
|
@ -30,6 +30,9 @@
|
|||||||
#include "Poco/DateTimeFormatter.h"
|
#include "Poco/DateTimeFormatter.h"
|
||||||
#include "Poco/DateTimeParser.h"
|
#include "Poco/DateTimeParser.h"
|
||||||
#include "Poco/String.h"
|
#include "Poco/String.h"
|
||||||
|
#include "Poco/UnicodeConverter.h"
|
||||||
|
#include "Poco/UTFString.h"
|
||||||
|
#include "Poco/UTF8String.h"
|
||||||
#include "Poco/Any.h"
|
#include "Poco/Any.h"
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -106,7 +109,7 @@ class Foundation_API VarHolder
|
|||||||
/// Only data types for which VarHolder specialization exists are supported.
|
/// Only data types for which VarHolder specialization exists are supported.
|
||||||
///
|
///
|
||||||
/// Provided are specializations for all C++ built-in types with addition of
|
/// Provided are specializations for all C++ built-in types with addition of
|
||||||
/// std::string, DateTime, LocalDateTime, Timestamp, std::vector<Var> and DynamicStruct.
|
/// std::string, Poco::UTF16String, DateTime, LocalDateTime, Timestamp, std::vector<Var> and DynamicStruct.
|
||||||
///
|
///
|
||||||
/// Additional types can be supported by adding specializations. When implementing specializations,
|
/// Additional types can be supported by adding specializations. When implementing specializations,
|
||||||
/// the only condition is that they reside in Poco namespace and implement the pure virtual functions
|
/// the only condition is that they reside in Poco namespace and implement the pure virtual functions
|
||||||
@ -208,6 +211,10 @@ public:
|
|||||||
/// Throws BadCastException. Must be overriden in a type
|
/// Throws BadCastException. Must be overriden in a type
|
||||||
/// specialization in order to suport the conversion.
|
/// specialization in order to suport the conversion.
|
||||||
|
|
||||||
|
virtual void convert(Poco::UTF16String& val) const;
|
||||||
|
/// Throws BadCastException. Must be overriden in a type
|
||||||
|
/// specialization in order to suport the conversion.
|
||||||
|
|
||||||
virtual bool isArray() const;
|
virtual bool isArray() const;
|
||||||
/// Returns true.
|
/// Returns true.
|
||||||
|
|
||||||
@ -534,6 +541,12 @@ inline void VarHolder::convert(std::string& /*val*/) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void VarHolder::convert(Poco::UTF16String& /*val*/) const
|
||||||
|
{
|
||||||
|
throw BadCastException("Can not convert to Poco::UTF16String");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool VarHolder::isArray() const
|
inline bool VarHolder::isArray() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -728,6 +741,12 @@ public:
|
|||||||
val = NumberFormatter::format(_val);
|
val = NumberFormatter::format(_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void convert(Poco::UTF16String& val) const
|
||||||
|
{
|
||||||
|
std::string str = NumberFormatter::format(_val);
|
||||||
|
Poco::UnicodeConverter::convert(str, val);
|
||||||
|
}
|
||||||
|
|
||||||
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
|
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
|
||||||
{
|
{
|
||||||
return cloneHolder(pVarHolder, _val);
|
return cloneHolder(pVarHolder, _val);
|
||||||
@ -861,6 +880,12 @@ public:
|
|||||||
val = NumberFormatter::format(_val);
|
val = NumberFormatter::format(_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void convert(Poco::UTF16String& val) const
|
||||||
|
{
|
||||||
|
std::string str = NumberFormatter::format(_val);
|
||||||
|
Poco::UnicodeConverter::convert(str, val);
|
||||||
|
}
|
||||||
|
|
||||||
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
|
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
|
||||||
{
|
{
|
||||||
return cloneHolder(pVarHolder, _val);
|
return cloneHolder(pVarHolder, _val);
|
||||||
@ -2280,15 +2305,15 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <>
|
||||||
class VarHolderImpl<std::basic_string<T> >: public VarHolder
|
class VarHolderImpl<std::string>: public VarHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VarHolderImpl(const char* pVal): _val(pVal)
|
VarHolderImpl(const char* pVal): _val(pVal)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
VarHolderImpl(const std::string& val): _val(val)
|
VarHolderImpl(const std::string& val) : _val(val)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2347,16 +2372,16 @@ public:
|
|||||||
|
|
||||||
void convert(bool& val) const
|
void convert(bool& val) const
|
||||||
{
|
{
|
||||||
static const std::string VAL_FALSE("false");
|
if (_val.empty())
|
||||||
static const std::string VAL_INT_FALSE("0");
|
|
||||||
|
|
||||||
if (_val.empty() ||
|
|
||||||
_val == VAL_INT_FALSE ||
|
|
||||||
(icompare(_val, VAL_FALSE) == 0))
|
|
||||||
{
|
{
|
||||||
val = false;
|
val = false;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else val = true;
|
|
||||||
|
static const std::string VAL_FALSE("false");
|
||||||
|
static const std::string VAL_INT_FALSE("0");
|
||||||
|
val = (_val != VAL_INT_FALSE &&
|
||||||
|
(icompare(_val, VAL_FALSE) != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void convert(float& val) const
|
void convert(float& val) const
|
||||||
@ -2383,6 +2408,11 @@ public:
|
|||||||
val = _val;
|
val = _val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void convert(Poco::UTF16String& val) const
|
||||||
|
{
|
||||||
|
Poco::UnicodeConverter::convert(_val, val);
|
||||||
|
}
|
||||||
|
|
||||||
void convert(DateTime& val) const
|
void convert(DateTime& val) const
|
||||||
{
|
{
|
||||||
int tzd = 0;
|
int tzd = 0;
|
||||||
@ -2415,7 +2445,7 @@ public:
|
|||||||
return cloneHolder(pVarHolder, _val);
|
return cloneHolder(pVarHolder, _val);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& value() const
|
const std:: string& value() const
|
||||||
{
|
{
|
||||||
return _val;
|
return _val;
|
||||||
}
|
}
|
||||||
@ -2430,14 +2460,14 @@ public:
|
|||||||
return _val.length();
|
return _val.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator[](std::string::size_type n)
|
char& operator[](std::string::size_type n)
|
||||||
{
|
{
|
||||||
if (n < size()) return _val.operator[](n);
|
if (n < size()) return _val.operator[](n);
|
||||||
|
|
||||||
throw RangeException("String index out of range");
|
throw RangeException("String index out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator[](std::string::size_type n) const
|
const char& operator[](std::string::size_type n) const
|
||||||
{
|
{
|
||||||
if (n < size()) return _val.operator[](n);
|
if (n < size()) return _val.operator[](n);
|
||||||
|
|
||||||
@ -2449,7 +2479,195 @@ private:
|
|||||||
VarHolderImpl(const VarHolderImpl&);
|
VarHolderImpl(const VarHolderImpl&);
|
||||||
VarHolderImpl& operator = (const VarHolderImpl&);
|
VarHolderImpl& operator = (const VarHolderImpl&);
|
||||||
|
|
||||||
std::basic_string<T> _val;
|
std::string _val;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class VarHolderImpl<UTF16String>: public VarHolder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VarHolderImpl(const char* pVal) : _val(Poco::UnicodeConverter::to<UTF16String>(pVal))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VarHolderImpl(const Poco::UTF16String& val) : _val(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~VarHolderImpl()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::type_info& type() const
|
||||||
|
{
|
||||||
|
return typeid(Poco::UTF16String);
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(Int8& val) const
|
||||||
|
{
|
||||||
|
int v = NumberParser::parse(toStdString());
|
||||||
|
convertToSmaller(v, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(Int16& val) const
|
||||||
|
{
|
||||||
|
int v = NumberParser::parse(toStdString());
|
||||||
|
convertToSmaller(v, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(Int32& val) const
|
||||||
|
{
|
||||||
|
val = NumberParser::parse(toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(Int64& val) const
|
||||||
|
{
|
||||||
|
val = NumberParser::parse64(toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(UInt8& val) const
|
||||||
|
{
|
||||||
|
unsigned int v = NumberParser::parseUnsigned(toStdString());
|
||||||
|
convertToSmallerUnsigned(v, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(UInt16& val) const
|
||||||
|
{
|
||||||
|
unsigned int v = NumberParser::parseUnsigned(toStdString());
|
||||||
|
convertToSmallerUnsigned(v, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(UInt32& val) const
|
||||||
|
{
|
||||||
|
val = NumberParser::parseUnsigned(toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(UInt64& val) const
|
||||||
|
{
|
||||||
|
val = NumberParser::parseUnsigned64(toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(bool& val) const
|
||||||
|
{
|
||||||
|
static const std::string VAL_FALSE("false");
|
||||||
|
static const std::string VAL_INT_FALSE("0");
|
||||||
|
|
||||||
|
if (_val.empty()) val = false;
|
||||||
|
|
||||||
|
std::string str;
|
||||||
|
UnicodeConverter::convert(_val, str);
|
||||||
|
val = (str != VAL_INT_FALSE &&
|
||||||
|
(icompare(str, VAL_FALSE) != 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(float& val) const
|
||||||
|
{
|
||||||
|
double v = NumberParser::parseFloat(toStdString());
|
||||||
|
convertToSmaller(v, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(double& val) const
|
||||||
|
{
|
||||||
|
val = NumberParser::parseFloat(toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(char& val) const
|
||||||
|
{
|
||||||
|
if (_val.empty())
|
||||||
|
val = '\0';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
UnicodeConverter::convert(_val, s);
|
||||||
|
val = s[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(Poco::UTF16String& val) const
|
||||||
|
{
|
||||||
|
val = _val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(std::string& val) const
|
||||||
|
{
|
||||||
|
UnicodeConverter::convert(_val, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(DateTime& val) const
|
||||||
|
{
|
||||||
|
int tzd = 0;
|
||||||
|
if (!DateTimeParser::tryParse(DateTimeFormat::ISO8601_FORMAT, toStdString(), val, tzd))
|
||||||
|
throw BadCastException("string -> DateTime");
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(LocalDateTime& ldt) const
|
||||||
|
{
|
||||||
|
int tzd = 0;
|
||||||
|
DateTime tmp;
|
||||||
|
if (!DateTimeParser::tryParse(DateTimeFormat::ISO8601_FORMAT, toStdString(), tmp, tzd))
|
||||||
|
throw BadCastException("string -> LocalDateTime");
|
||||||
|
|
||||||
|
ldt = LocalDateTime(tzd, tmp, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(Timestamp& ts) const
|
||||||
|
{
|
||||||
|
int tzd = 0;
|
||||||
|
DateTime tmp;
|
||||||
|
if (!DateTimeParser::tryParse(DateTimeFormat::ISO8601_FORMAT, toStdString(), tmp, tzd))
|
||||||
|
throw BadCastException("string -> Timestamp");
|
||||||
|
|
||||||
|
ts = tmp.timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
|
||||||
|
{
|
||||||
|
return cloneHolder(pVarHolder, _val);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Poco::UTF16String& value() const
|
||||||
|
{
|
||||||
|
return _val;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isString() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t size() const
|
||||||
|
{
|
||||||
|
return _val.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
UTF16Char& operator[](Poco::UTF16String::size_type n)
|
||||||
|
{
|
||||||
|
if (n < size()) return _val.operator[](n);
|
||||||
|
|
||||||
|
throw RangeException("String index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
const UTF16Char& operator[](Poco::UTF16String::size_type n) const
|
||||||
|
{
|
||||||
|
if (n < size()) return _val.operator[](n);
|
||||||
|
|
||||||
|
throw RangeException("String index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VarHolderImpl();
|
||||||
|
VarHolderImpl(const VarHolderImpl&);
|
||||||
|
VarHolderImpl& operator = (const VarHolderImpl&);
|
||||||
|
|
||||||
|
std::string toStdString() const
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
UnicodeConverter::convert(_val, str);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
Poco::UTF16String _val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,6 +108,23 @@ public:
|
|||||||
convert(f, l, t);
|
convert(f, l, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static T to(const char* pChar)
|
||||||
|
{
|
||||||
|
T utfStr;
|
||||||
|
Poco::UnicodeConverter::convert(pChar, utfStr);
|
||||||
|
return utfStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static T to(const std::string& str)
|
||||||
|
{
|
||||||
|
T utfStr;
|
||||||
|
Poco::UnicodeConverter::convert(str, utfStr);
|
||||||
|
return utfStr;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static std::size_t UTFStrlen(const T* ptr)
|
static std::size_t UTFStrlen(const T* ptr)
|
||||||
/// Returns the length (in characters) of a zero-terminated UTF string.
|
/// Returns the length (in characters) of a zero-terminated UTF string.
|
||||||
|
@ -175,7 +175,7 @@ void TextConverterTest::testLatin1toUTF8()
|
|||||||
int errors = converter.convert(latin1Text, result0);
|
int errors = converter.convert(latin1Text, result0);
|
||||||
assert (result0 == utf8Text);
|
assert (result0 == utf8Text);
|
||||||
assert (errors == 0);
|
assert (errors == 0);
|
||||||
assertEqual (result0.size(), 7);
|
assertEqual((long) result0.size(), 7);
|
||||||
|
|
||||||
std::string result1;
|
std::string result1;
|
||||||
errors = converter.convert(latin1Chars, 6, result1);
|
errors = converter.convert(latin1Chars, 6, result1);
|
||||||
@ -200,13 +200,13 @@ void TextConverterTest::testLatin2toUTF8()
|
|||||||
int errors = converter.convert(latinText, result0);
|
int errors = converter.convert(latinText, result0);
|
||||||
assertEqual (result0, utf8Text);
|
assertEqual (result0, utf8Text);
|
||||||
assertEqual (errors, 0);
|
assertEqual (errors, 0);
|
||||||
assertEqual (result0.size(), 49);
|
assertEqual((long) result0.size(), 49);
|
||||||
|
|
||||||
std::string result1;
|
std::string result1;
|
||||||
errors = converter.convert(latinChars, 25, result1);
|
errors = converter.convert(latinChars, 25, result1);
|
||||||
assertEqual (result1, utf8Text);
|
assertEqual (result1, utf8Text);
|
||||||
assertEqual (errors, 0);
|
assertEqual (errors, 0);
|
||||||
assertEqual (result1.size(), 49);
|
assertEqual((long) result1.size(), 49);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -226,13 +226,13 @@ void TextConverterTest::testLatin9toUTF8()
|
|||||||
int errors = converter.convert(latinText, result0);
|
int errors = converter.convert(latinText, result0);
|
||||||
assertEqual (result0, utf8Text);
|
assertEqual (result0, utf8Text);
|
||||||
assertEqual (errors, 0);
|
assertEqual (errors, 0);
|
||||||
assertEqual (result0.size(), 43);
|
assertEqual((long) result0.size(), 43);
|
||||||
|
|
||||||
std::string result1;
|
std::string result1;
|
||||||
errors = converter.convert(latinChars, 25, result1);
|
errors = converter.convert(latinChars, 25, result1);
|
||||||
assertEqual (result1, utf8Text);
|
assertEqual(result1, utf8Text);
|
||||||
assertEqual (errors, 0);
|
assertEqual((long) errors, 0);
|
||||||
assertEqual (result1.size(), 43);
|
assertEqual((long) result1.size(), 43);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -252,13 +252,13 @@ void TextConverterTest::testCP1250toUTF8()
|
|||||||
int errors = converter.convert(latinText, result0);
|
int errors = converter.convert(latinText, result0);
|
||||||
assertEqual (result0, utf8Text);
|
assertEqual (result0, utf8Text);
|
||||||
assertEqual (errors, 0);
|
assertEqual (errors, 0);
|
||||||
assertEqual (result0.size(), 49);
|
assertEqual((long) result0.size(), 49);
|
||||||
|
|
||||||
std::string result1;
|
std::string result1;
|
||||||
errors = converter.convert(latinChars, 25, result1);
|
errors = converter.convert(latinChars, 25, result1);
|
||||||
assertEqual (result1, utf8Text);
|
assertEqual(result1, utf8Text);
|
||||||
assertEqual (errors, 0);
|
assertEqual((long) errors, 0);
|
||||||
assertEqual (result1.size(), 49);
|
assertEqual((long) result1.size(), 49);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -277,13 +277,13 @@ void TextConverterTest::testCP1251toUTF8()
|
|||||||
int errors = converter.convert(latinText, result0);
|
int errors = converter.convert(latinText, result0);
|
||||||
assertEqual (result0, utf8Text);
|
assertEqual (result0, utf8Text);
|
||||||
assertEqual (errors, 0);
|
assertEqual (errors, 0);
|
||||||
assertEqual (result0.size(), 62);
|
assertEqual((long) result0.size(), 62);
|
||||||
|
|
||||||
std::string result1;
|
std::string result1;
|
||||||
errors = converter.convert(latinChars, 31, result1);
|
errors = converter.convert(latinChars, 31, result1);
|
||||||
assertEqual (result1, utf8Text);
|
assertEqual (result1, utf8Text);
|
||||||
assertEqual (errors, 0);
|
assertEqual (errors, 0);
|
||||||
assertEqual (result1.size(), 62);
|
assertEqual((long) result1.size(), 62);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -301,15 +301,15 @@ void TextConverterTest::testCP1252toUTF8()
|
|||||||
|
|
||||||
std::string result0;
|
std::string result0;
|
||||||
int errors = converter.convert(latinText, result0);
|
int errors = converter.convert(latinText, result0);
|
||||||
assertEqual (result0, utf8Text);
|
assertEqual(result0, utf8Text);
|
||||||
assertEqual (errors, 0);
|
assertEqual(errors, 0);
|
||||||
assertEqual (result0.size(), 43);
|
assertEqual((long) result0.size(), 43);
|
||||||
|
|
||||||
std::string result1;
|
std::string result1;
|
||||||
errors = converter.convert(latinChars, 25, result1);
|
errors = converter.convert(latinChars, 25, result1);
|
||||||
assertEqual (result1, utf8Text);
|
assertEqual(result1, utf8Text);
|
||||||
assertEqual (errors, 0);
|
assertEqual(errors, 0);
|
||||||
assertEqual (result1.size(), 43);
|
assertEqual((long) result1.size(), 43);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "Poco/Foundation.h"
|
#include "Poco/Foundation.h"
|
||||||
#include "CppUnit/TestCase.h"
|
#include "CppUnit/TestCase.h"
|
||||||
#include "Poco/UnicodeConverter.h"
|
#include "Poco/UnicodeConverter.h"
|
||||||
|
#include "Poco/UTFString.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
@ -46,11 +47,16 @@ private:
|
|||||||
// Convert from UTF-8 to wide
|
// Convert from UTF-8 to wide
|
||||||
T wtext, wtext2, wtext3;
|
T wtext, wtext2, wtext3;
|
||||||
Poco::UnicodeConverter::convert(text, wtext);
|
Poco::UnicodeConverter::convert(text, wtext);
|
||||||
|
if (sizeof(T) == 2)
|
||||||
|
assert(Poco::utfStringLength(wtext.data()) == 8);
|
||||||
|
else if (sizeof(T) == 4)
|
||||||
|
assert(Poco::utfStringLength(wtext.data()) == 5);
|
||||||
Poco::UnicodeConverter::convert((const char*) supp, strlen((const char*) supp), wtext2);
|
Poco::UnicodeConverter::convert((const char*) supp, strlen((const char*) supp), wtext2);
|
||||||
Poco::UnicodeConverter::convert((const char*) supp, wtext3);
|
Poco::UnicodeConverter::convert((const char*)supp, wtext3);
|
||||||
|
assert(wtext == wtext2);
|
||||||
|
assert(wtext == wtext3);
|
||||||
|
|
||||||
std::string text2, text3, text4;
|
std::string text2, text3, text4;
|
||||||
|
|
||||||
assert (text != text2);
|
assert (text != text2);
|
||||||
assert (text != text3);
|
assert (text != text3);
|
||||||
assert (text != text4);
|
assert (text != text4);
|
||||||
|
@ -1115,7 +1115,7 @@ void VarTest::testString()
|
|||||||
Poco::UInt64 s9;
|
Poco::UInt64 s9;
|
||||||
float s10;
|
float s10;
|
||||||
double s11;
|
double s11;
|
||||||
bool s12;
|
bool s12 = false;
|
||||||
char s13;
|
char s13;
|
||||||
a1.convert(s1);
|
a1.convert(s1);
|
||||||
a1.convert(s2);
|
a1.convert(s2);
|
||||||
|
@ -1,6 +1,83 @@
|
|||||||
POCO C++ Libraries Release Notes
|
POCO C++ Libraries Release Notes
|
||||||
AAAIntroduction
|
AAAIntroduction
|
||||||
|
|
||||||
|
!!!Release 1.5.3
|
||||||
|
|
||||||
|
!!Summary of Changes
|
||||||
|
|
||||||
|
- fixed GH# 316: Poco::DateTimeFormatter::append() gives wrong result for
|
||||||
|
Poco::LocalDateTime
|
||||||
|
- Poco::Data::MySQL: added SQLite thread cleanup handler
|
||||||
|
- Poco::Net::X509Certificate: improved and fixed domain name verification for
|
||||||
|
wildcard domains
|
||||||
|
- added Poco::Clock class, which uses a system-provided monotonic clock
|
||||||
|
(if available) and is thus not affected by system realtime clock changes.
|
||||||
|
Monotonic Clock is available on Windows, Linux, OS X and on POSIX platforms
|
||||||
|
supporting clock_gettime() and CLOCK_MONOTONIC.
|
||||||
|
- Poco::Timer, Poco::Stopwatch, Poco::TimedNotificationQueue and Poco::Util::Timer
|
||||||
|
have been changed to use Poco::Clock instead of Poco::Timestamp and are now
|
||||||
|
unaffected by system realtime clock changes.
|
||||||
|
- fixed GH# 350: Memory leak in Data/ODBC with BLOB
|
||||||
|
- Correctly set MySQL time_type for Poco::Data::Date.
|
||||||
|
- fixed GH #352: Removed redundant #includes and fixed spelling mistakes.
|
||||||
|
- fixed setting of MYSQL_BIND is_unsigned value.
|
||||||
|
- fixed GH #360: CMakeLists foundation: add Clock.cpp in the list of source files
|
||||||
|
- Add extern "C" around <net/if.h> on HPUX platform.
|
||||||
|
- added runtests.sh
|
||||||
|
- fixed CPPUNIT_IGNORE parsing
|
||||||
|
- fixed Glob from start path, for platforms not alowing transverse from root (Android)
|
||||||
|
- added NTPClient (Rangel Reale)
|
||||||
|
- added PowerShell build script
|
||||||
|
- added SmartOS build support
|
||||||
|
- fix warnings in headers
|
||||||
|
- XMLWriter: removed unnecessary apostrophe escaping (&apos)
|
||||||
|
- MongoDB: use Int32 for messageLength
|
||||||
|
- fixed GH #380: SecureSocket+DialogSocket crashes with SIGSEGV when timeout occours
|
||||||
|
- Improve RSADigestEngine, using Poco::Crypto::DigestEngine to calculate hash before signing
|
||||||
|
- added Poco::PBKDF2Engine
|
||||||
|
- Fixed GH #380: SecureSocket+DialogSocket crashes with SIGSEGV when timeout occours
|
||||||
|
- added support for a 'Priority' attribute on cookies.
|
||||||
|
- GH #386: fixed bug in MailMessage without content-transfer-encoding header
|
||||||
|
- GH #384: ew hash algorithms support for RSADigestEngine
|
||||||
|
- fixed Clock overflow bug on Windows
|
||||||
|
- Poco::ByteOrder now uses intrinsics, if available
|
||||||
|
- CMake: added /bigobj option for msvc
|
||||||
|
- Fix typo to restore Net/TestSuite_x64_vs120 build
|
||||||
|
- correct path for CONFIGURE_FILE in CMakeLists.txt
|
||||||
|
- Building Poco 1.5.2 for Synology RS812+ (Intel Atom) (honor POCO_NO_INOTIFY)
|
||||||
|
- added WEC2013 support to buildwin.cmd and buildwin.ps1
|
||||||
|
- HTMLForm: in URL encoding, percent-encode more characters
|
||||||
|
- Fixed #include <linux/if.h> conflict with other libraries
|
||||||
|
- Poco::Net::X509Certificate::verify() no longer uses DNS reverse lookups to validate host names
|
||||||
|
- cert hostname validation is case insensitive and stricter for wildcard certificates
|
||||||
|
- TCPServer: do not reduce the capacity of the default ThreadPool
|
||||||
|
- added POCO_LOG_DEBUG flag
|
||||||
|
- Zip: fixed a crash caused by an I/O error
|
||||||
|
- added runtest script for windows
|
||||||
|
- added SQlite Full Text Search support
|
||||||
|
- added Thread::trySleep() and Thread::wakeUp()
|
||||||
|
- fixed GH #410: Bug in JSON::Object.stringify() in 1.5.2
|
||||||
|
- fixed GH #362: Defect in Var::parseString when there is no space between value and newline
|
||||||
|
- fixed GH #314: JSON parsing bug
|
||||||
|
- added GH #313: MetaColumn additions for Data::ODBC and Data::SQLite
|
||||||
|
- fixed GH #346: Make Poco::Data::Date and Poco::Data::Time compare functions const.
|
||||||
|
- fixed GH #341: Compiling poco-1.5.2 for Cygwin
|
||||||
|
- fixed GH #305: There are bugs in Buffer.h
|
||||||
|
- fixed GH #321: trivial build fixes (BB QNX build)
|
||||||
|
- fixed GH #440: MongoDB ObjectId string formatting
|
||||||
|
- added SevenZip library (Guenter Obiltschnig)
|
||||||
|
- fixed GH #442: Use correct prefix length field of Windows IP_ADAPTER_PREFIX structure
|
||||||
|
- improved GH #328: NetworkInterface on Windows XP
|
||||||
|
- fixed GH #154 Add support for MYSQL_TYPE_NEWDECIMAL to Poco::Data::MySQL
|
||||||
|
- fixed GH #290: Unicode support
|
||||||
|
|
||||||
|
!!Incompatible Changes and Possible Transition Issues
|
||||||
|
|
||||||
|
- Data::ODBC: UTF-16 Unicode is now directly mapped and recognized as type by ODBC.
|
||||||
|
This may cause behavior different from previosu versions, especially with Any and
|
||||||
|
Dynamic::Var bindings.
|
||||||
|
|
||||||
|
|
||||||
!!!Release 1.5.2
|
!!!Release 1.5.2
|
||||||
|
|
||||||
!!Summary of Changes
|
!!Summary of Changes
|
||||||
|
Loading…
x
Reference in New Issue
Block a user