mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 18:20:26 +01:00
#3318: Data: Support Poco::UUID for data binding
This commit is contained in:
parent
a95c591e0a
commit
7569ccf82b
@ -19,7 +19,6 @@
|
||||
#include "Poco/ActiveRecord/ActiveRecordLib.h"
|
||||
#include "Poco/ActiveRecord/Context.h"
|
||||
#include "Poco/ActiveRecord/IDTraits.h"
|
||||
#include "Poco/ActiveRecord/TypeHandler.h"
|
||||
#include "Poco/DateTime.h"
|
||||
#include "Poco/RefCountedObject.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
|
@ -1,70 +0,0 @@
|
||||
//
|
||||
// TypeHandler.h
|
||||
//
|
||||
// Library: ActiveRecord
|
||||
// Package: ActiveRecord
|
||||
// Module: TypeHandler
|
||||
//
|
||||
// Copyright (c) 2020, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef ActiveRecord_TypeHandler_INCLUDED
|
||||
#define ActiveRecord_TypeHandler_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/TypeHandler.h"
|
||||
#include "Poco/ThreadLocal.h"
|
||||
#include "Poco/UUID.h"
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
template <>
|
||||
class TypeHandler<Poco::UUID>
|
||||
{
|
||||
public:
|
||||
using UUIDMap = std::map<std::size_t, std::string>;
|
||||
|
||||
static std::size_t size()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void bind(std::size_t pos, const Poco::UUID& uuid, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
|
||||
{
|
||||
static Poco::ThreadLocal<UUIDMap> uuidMap;
|
||||
std::string& uuidString = (*uuidMap)[pos];
|
||||
uuidString = uuid.toString();
|
||||
TypeHandler<std::string>::bind(pos++, uuidString, pBinder, dir);
|
||||
}
|
||||
|
||||
static void extract(std::size_t pos, Poco::UUID& uuid, const Poco::UUID& deflt, AbstractExtractor::Ptr pExtr)
|
||||
{
|
||||
std::string defltString = deflt.toString();
|
||||
std::string uuidString;
|
||||
TypeHandler<std::string>::extract(pos++, uuidString, defltString, pExtr);
|
||||
uuid.parse(uuidString);
|
||||
}
|
||||
|
||||
static void prepare(std::size_t pos, const Poco::UUID& uuid, AbstractPreparator::Ptr pPrep)
|
||||
{
|
||||
static Poco::ThreadLocal<UUIDMap> uuidMap;
|
||||
std::string& uuidString = (*uuidMap)[pos];
|
||||
uuidString = uuid.toString();
|
||||
TypeHandler<std::string>::prepare(pos++, uuidString, pPrep);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
|
||||
#endif // ActiveRecord_TypeHandler_INCLUDED
|
||||
|
@ -104,6 +104,9 @@ public:
|
||||
virtual void bind(std::size_t pos, const Time& val, Direction dir);
|
||||
/// Binds a Time.
|
||||
|
||||
virtual void bind(std::size_t pos, const UUID& val, Direction dir);
|
||||
/// Binds a UUID.
|
||||
|
||||
virtual void bind(std::size_t pos, const NullData& val, Direction dir);
|
||||
/// Binds a null.
|
||||
|
||||
|
@ -110,6 +110,9 @@ public:
|
||||
virtual bool extract(std::size_t pos, Time& val);
|
||||
/// Extracts a Time. Returns false if null was received.
|
||||
|
||||
virtual bool extract(std::size_t pos, UUID& val);
|
||||
/// Extracts a UUID. Returns false if null was received.
|
||||
|
||||
virtual bool extract(std::size_t pos, Any& val);
|
||||
/// Extracts an Any. Returns false if null was received.
|
||||
|
||||
|
@ -211,6 +211,13 @@ void Binder::bind(std::size_t pos, const Time& val, Direction dir)
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const UUID& val, Direction dir)
|
||||
{
|
||||
std::string str = val.toString();
|
||||
bind(pos, str, dir);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const NullData&, Direction dir)
|
||||
{
|
||||
poco_assert(dir == PD_IN);
|
||||
|
@ -204,6 +204,18 @@ bool Extractor::extract(std::size_t pos, Time& val)
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, UUID& val)
|
||||
{
|
||||
std::string str;
|
||||
if (extract(pos, str))
|
||||
{
|
||||
val.parse(str);
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Any& val)
|
||||
{
|
||||
return false;
|
||||
|
@ -496,6 +496,15 @@ void MySQLTest::testDouble()
|
||||
}
|
||||
|
||||
|
||||
void MySQLTest::testUUID()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
recreateUUIDsTable();
|
||||
_pExecutor->uuids();
|
||||
}
|
||||
|
||||
|
||||
void MySQLTest::testTuple()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
@ -779,6 +788,15 @@ void MySQLTest::recreateFloatsTable()
|
||||
}
|
||||
|
||||
|
||||
void MySQLTest::recreateUUIDsTable()
|
||||
{
|
||||
dropTable("Strings");
|
||||
try { *_pSession << "CREATE TABLE Strings (str CHAR(36))", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateUUIDsTable()"); }
|
||||
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateUUIDsTable()"); }
|
||||
}
|
||||
|
||||
|
||||
void MySQLTest::recreateTuplesTable()
|
||||
{
|
||||
dropTable("Tuples");
|
||||
@ -904,6 +922,7 @@ CppUnit::Test* MySQLTest::suite()
|
||||
CppUnit_addTest(pSuite, MySQLTest, testUnsignedInts);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testFloat);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testDouble);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testUUID);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testTuple);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testTupleVector);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testInternalExtraction);
|
||||
|
@ -84,6 +84,8 @@ public:
|
||||
void testFloat();
|
||||
void testDouble();
|
||||
|
||||
void testUUID();
|
||||
|
||||
void testTuple();
|
||||
void testTupleVector();
|
||||
|
||||
@ -119,6 +121,7 @@ private:
|
||||
void recreateIntsTable();
|
||||
void recreateUnsignedIntsTable();
|
||||
void recreateFloatsTable();
|
||||
void recreateUUIDsTable();
|
||||
void recreateTuplesTable();
|
||||
void recreateVectorsTable();
|
||||
void recreateNullableIntTable();
|
||||
|
@ -545,6 +545,29 @@ void SQLExecutor::doubles()
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::uuids()
|
||||
{
|
||||
std::string funct = "uuids()";
|
||||
Poco::UUID data("da8b9c4d-faa0-44e1-b834-ece1e7d31cd5");
|
||||
Poco::UUID ret;
|
||||
|
||||
try { *_pSession << "INSERT INTO Strings VALUES (?)", use(data), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||
|
||||
int count = 0;
|
||||
try { *_pSession << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||
assertTrue (count == 1);
|
||||
|
||||
try { *_pSession << "SELECT str FROM Strings", into(ret), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||
assertTrue (ret == data);
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::insertSingleBulkVec()
|
||||
{
|
||||
std::string funct = "insertSingleBulkVec()";
|
||||
|
@ -86,6 +86,7 @@ public:
|
||||
void unsignedInts();
|
||||
void floats();
|
||||
void doubles();
|
||||
void uuids();
|
||||
void tuples();
|
||||
void tupleVector();
|
||||
|
||||
|
@ -322,6 +322,9 @@ public:
|
||||
void bind(std::size_t pos, const std::list<DateTime>& val, Direction dir);
|
||||
/// Binds a DateTime list.
|
||||
|
||||
void bind(std::size_t pos, const UUID& val, Direction dir);
|
||||
/// Binds a UUID.
|
||||
|
||||
void bind(std::size_t pos, const NullData& val, Direction dir);
|
||||
/// Binds a null. In-bound only.
|
||||
|
||||
@ -367,6 +370,7 @@ private:
|
||||
typedef std::vector<AnyVec> AnyVecVec;
|
||||
typedef std::map<char*, std::string*> StringMap;
|
||||
typedef std::map<UTF16String::value_type*, UTF16String*> UTF16StringMap;
|
||||
typedef std::map<char*, UUID*> UUIDMap;
|
||||
typedef std::map<SQL_DATE_STRUCT*, Date*> DateMap;
|
||||
typedef std::map<SQL_TIME_STRUCT*, Time*> TimeMap;
|
||||
typedef std::map<SQL_TIMESTAMP_STRUCT*, DateTime*> TimestampMap;
|
||||
@ -998,6 +1002,7 @@ private:
|
||||
TimestampMap _timestamps;
|
||||
StringMap _strings;
|
||||
UTF16StringMap _utf16Strings;
|
||||
UUIDMap _uuids;
|
||||
|
||||
DateVecVec _dateVecVec;
|
||||
TimeVecVec _timeVecVec;
|
||||
|
@ -305,6 +305,9 @@ public:
|
||||
bool extract(std::size_t pos, std::list<Poco::DateTime>& val);
|
||||
/// Extracts a DateTime list.
|
||||
|
||||
bool extract(std::size_t pos, Poco::UUID& val);
|
||||
/// Extracts a UUID.
|
||||
|
||||
bool extract(std::size_t pos, Poco::Any& val);
|
||||
/// Extracts an Any.
|
||||
|
||||
@ -567,6 +570,9 @@ private:
|
||||
case MetaColumn::FDT_TIMESTAMP:
|
||||
{ return extAny<T, Poco::DateTime>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_UUID:
|
||||
{ return extAny<T, Poco::UUID>(pos, val); }
|
||||
|
||||
default:
|
||||
throw DataFormatException("Unsupported data type.");
|
||||
}
|
||||
|
@ -353,6 +353,9 @@ public:
|
||||
void prepare(std::size_t pos, const std::list<Poco::DateTime>& val);
|
||||
/// Prepares a DateTime list.
|
||||
|
||||
void prepare(std::size_t pos, const Poco::UUID& val);
|
||||
/// Prepares a UUID.
|
||||
|
||||
void prepare(std::size_t pos, const Poco::Any& val);
|
||||
/// Prepares an Any.
|
||||
|
||||
@ -548,6 +551,12 @@ private:
|
||||
else
|
||||
return prepareFixedSize<DateTime>(pos, SQL_C_TYPE_TIMESTAMP);
|
||||
|
||||
case MetaColumn::FDT_UUID:
|
||||
if (pVal)
|
||||
return prepareFixedSize<DateTime>(pos, SQL_C_BINARY, 16);
|
||||
else
|
||||
return prepareFixedSize<DateTime>(pos, SQL_C_BINARY);
|
||||
|
||||
default:
|
||||
throw DataFormatException("Unsupported data type.");
|
||||
}
|
||||
@ -1173,6 +1182,12 @@ inline void Preparator::prepare(std::size_t pos, const std::list<Poco::DateTime>
|
||||
}
|
||||
|
||||
|
||||
inline void Preparator::prepare(std::size_t pos, const Poco::UUID&)
|
||||
{
|
||||
prepareCharArray<char, DT_CHAR_ARRAY>(pos, SQL_C_BINARY, 16, 16);
|
||||
}
|
||||
|
||||
|
||||
inline void Preparator::prepare(std::size_t pos, const Poco::Any& val)
|
||||
{
|
||||
prepareImpl<std::vector<Poco::Any> >(pos);
|
||||
|
@ -80,6 +80,10 @@ void Binder::freeMemory()
|
||||
UTF16CharPtrVec::iterator endUTF16Chr = _utf16CharPtrs.end();
|
||||
for (; itUTF16Chr != endUTF16Chr; ++itUTF16Chr) std::free(*itUTF16Chr);
|
||||
|
||||
UUIDMap::iterator itUUID = _uuids.begin();
|
||||
UUIDMap::iterator itUUIDEnd = _uuids.end();
|
||||
for(; itUUID != itUUIDEnd; ++itUUID) std::free(itUUID->first);
|
||||
|
||||
BoolPtrVec::iterator itBool = _boolPtrs.begin();
|
||||
BoolPtrVec::iterator endBool = _boolPtrs.end();
|
||||
for (; itBool != endBool; ++itBool) delete [] *itBool;
|
||||
@ -295,6 +299,38 @@ void Binder::bind(std::size_t pos, const Poco::DateTime& val, Direction dir)
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const UUID& val, Direction dir)
|
||||
{
|
||||
SQLINTEGER size = (SQLINTEGER) 16;
|
||||
SQLLEN* pLenIn = new SQLLEN;
|
||||
*pLenIn = size;
|
||||
|
||||
_lengthIndicator.push_back(pLenIn);
|
||||
|
||||
char* pUUID = new char[16];
|
||||
val.copyTo(pUUID);
|
||||
|
||||
_uuids.insert(UUIDMap::value_type(pUUID, const_cast<UUID*>(&val)));
|
||||
|
||||
SQLINTEGER colSize = 0;
|
||||
SQLSMALLINT decDigits = 0;
|
||||
|
||||
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||
(SQLUSMALLINT) pos + 1,
|
||||
toODBCDirection(dir),
|
||||
SQL_C_BINARY,
|
||||
SQL_GUID,
|
||||
colSize,
|
||||
decDigits,
|
||||
(SQLPOINTER) pUUID,
|
||||
0,
|
||||
_lengthIndicator.back())))
|
||||
{
|
||||
throw StatementException(_rStmt, "SQLBindParameter(UUID)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const NullData& val, Direction dir)
|
||||
{
|
||||
if (isOutBound(dir) || !isInBound(dir))
|
||||
@ -392,6 +428,14 @@ void Binder::synchronize()
|
||||
for(; it != end; ++it)
|
||||
it->second->assign(it->first, std::strlen(it->first));
|
||||
}
|
||||
|
||||
if (_uuids.size())
|
||||
{
|
||||
UUIDMap::iterator it = _uuids.begin();
|
||||
UUIDMap::iterator end = _uuids.end();
|
||||
for(; it != end; ++it)
|
||||
it->second->copyFrom(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -405,6 +449,7 @@ void Binder::reset()
|
||||
_times.clear();
|
||||
_timestamps.clear();
|
||||
_strings.clear();
|
||||
_uuids.clear();
|
||||
_dateVecVec.clear();
|
||||
_timeVecVec.clear();
|
||||
_dateTimeVecVec.clear();
|
||||
|
@ -224,6 +224,20 @@ bool Extractor::extractBoundImplContainer<std::list<Poco::DateTime> >(std::size_
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
bool Extractor::extractBoundImpl<Poco::UUID>(std::size_t pos, Poco::UUID& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
|
||||
std::size_t dataSize = _pPreparator->actualDataSize(pos);
|
||||
checkDataSize(dataSize);
|
||||
char* pBuffer = *AnyCast<char*>(&_pPreparator->at(pos));
|
||||
val.copyFrom(pBuffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
bool Extractor::extractBoundImplContainer<std::vector<bool> >(std::size_t pos,
|
||||
std::vector<bool>& val)
|
||||
@ -504,6 +518,33 @@ bool Extractor::extractManualImpl<Poco::DateTime>(std::size_t pos,
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
bool Extractor::extractManualImpl<Poco::UUID>(std::size_t pos,
|
||||
Poco::UUID& val,
|
||||
SQLSMALLINT cType)
|
||||
{
|
||||
char buffer[16];
|
||||
resizeLengths(pos);
|
||||
|
||||
SQLRETURN rc = SQLGetData(_rStmt,
|
||||
(SQLUSMALLINT) pos + 1,
|
||||
cType, //C data type
|
||||
&buffer, //returned value
|
||||
sizeof(buffer), //buffer length
|
||||
&_lengths[pos]); //length indicator
|
||||
|
||||
if (Utility::isError(rc))
|
||||
throw StatementException(_rStmt, "SQLGetData()");
|
||||
|
||||
if (isNullLengthIndicator(_lengths[pos]))
|
||||
return false;
|
||||
else
|
||||
val.copyFrom(buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Int32& val)
|
||||
{
|
||||
if (Preparator::DE_MANUAL == _dataExtraction)
|
||||
@ -911,6 +952,15 @@ bool Extractor::extract(std::size_t pos, std::list<Poco::DateTime>& val)
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::UUID& val)
|
||||
{
|
||||
if (Preparator::DE_MANUAL == _dataExtraction)
|
||||
return extractManualImpl(pos, val, SQL_C_BINARY);
|
||||
else
|
||||
return extractBoundImpl(pos, val);
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Int8& val)
|
||||
{
|
||||
if (Preparator::DE_MANUAL == _dataExtraction)
|
||||
|
@ -102,9 +102,6 @@ void ODBCMetaColumn::init()
|
||||
case SQL_CHAR:
|
||||
case SQL_VARCHAR:
|
||||
case SQL_LONGVARCHAR:
|
||||
#ifdef SQL_GUID
|
||||
case SQL_GUID:
|
||||
#endif
|
||||
setType(MetaColumn::FDT_STRING); break;
|
||||
|
||||
case SQL_WCHAR:
|
||||
@ -168,6 +165,9 @@ void ODBCMetaColumn::init()
|
||||
case SQL_TYPE_TIMESTAMP:
|
||||
setType(MetaColumn::FDT_TIMESTAMP); break;
|
||||
|
||||
case SQL_GUID:
|
||||
setType(MetaColumn::FDT_UUID); break;
|
||||
|
||||
default:
|
||||
throw DataFormatException("Unsupported data type.");
|
||||
}
|
||||
|
@ -37,6 +37,9 @@ endif
|
||||
ifeq (0, $(shell test -e /opt/postgresql/lib$(LIB64SUFFIX); echo $$?))
|
||||
SYSLIBS += -L/opt/postgresql/lib$(LIB64SUFFIX)
|
||||
endif
|
||||
ifeq (0, $(shell test -e /usr/local/opt/libpq/lib; echo $$?))
|
||||
SYSLIBS += -L/usr/local/opt/libpq/lib$(LIB64SUFFIX)
|
||||
endif
|
||||
SYSLIBS += -lpq
|
||||
|
||||
objects = Extractor Binder SessionImpl Connector \
|
||||
|
@ -108,6 +108,9 @@ public:
|
||||
virtual void bind(std::size_t pos, const Time& val, Direction dir = PD_IN);
|
||||
/// Binds a Time.
|
||||
|
||||
virtual void bind(std::size_t pos, const UUID& val, Direction dir = PD_IN);
|
||||
/// Binds a UUID.
|
||||
|
||||
virtual void bind(std::size_t pos, const NullData& val, Direction dir = PD_IN);
|
||||
/// Binds a null.
|
||||
|
||||
|
@ -109,6 +109,9 @@ public:
|
||||
virtual bool extract(std::size_t pos, Time& val);
|
||||
/// Extracts a Time. Returns false if null was received.
|
||||
|
||||
virtual bool extract(std::size_t pos, UUID& val);
|
||||
/// Extracts a UUID. Returns false if null was received.
|
||||
|
||||
virtual bool extract(std::size_t pos, Any& val);
|
||||
/// Extracts an Any. Returns false if null was received.
|
||||
|
||||
|
@ -271,6 +271,7 @@ inline const void* InputParameter::pInternalRepresentation() const
|
||||
case Poco::Data::MetaColumn::FDT_DATE:
|
||||
case Poco::Data::MetaColumn::FDT_TIME:
|
||||
case Poco::Data::MetaColumn::FDT_TIMESTAMP:
|
||||
case Poco::Data::MetaColumn::FDT_UUID:
|
||||
return _stringVersionRepresentation.c_str();
|
||||
|
||||
case Poco::Data::MetaColumn::FDT_BLOB:
|
||||
|
@ -176,6 +176,13 @@ void Binder::bind(std::size_t pos, const Time& val, Direction dir)
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const UUID& val, Direction dir)
|
||||
{
|
||||
poco_assert(dir == PD_IN);
|
||||
realBind(pos, Poco::Data::MetaColumn::FDT_UUID, &val, sizeof(UUID));
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const NullData&, Direction dir)
|
||||
{
|
||||
poco_assert(dir == PD_IN);
|
||||
@ -293,6 +300,14 @@ void Binder::updateBindVectorToCurrentValues()
|
||||
const Poco::Data::CLOB& clob = * static_cast<const Poco::Data::CLOB*>(itr->pData());
|
||||
itr->setNonStringVersionRepresentation(static_cast<const void*> (clob.rawContent()), clob.size());
|
||||
}
|
||||
break;
|
||||
|
||||
case Poco::Data::MetaColumn::FDT_UUID:
|
||||
{
|
||||
const Poco::UUID& uuid = * static_cast<const Poco::UUID*>(itr->pData());
|
||||
itr->setStringVersionRepresentation(uuid.toString());
|
||||
}
|
||||
break;
|
||||
|
||||
case Poco::Data::MetaColumn::FDT_UNKNOWN:
|
||||
default:
|
||||
|
@ -432,6 +432,19 @@ bool Extractor::extract(std::size_t pos, Time& val)
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, UUID& val)
|
||||
{
|
||||
OutputParameter outputParameter = extractPreamble(pos);
|
||||
|
||||
if (isColumnNull(outputParameter))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return val.tryParse(outputParameter.pData());
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Any& val)
|
||||
{
|
||||
return extractStringImpl(pos, val);
|
||||
@ -583,6 +596,14 @@ bool Extractor::extractToDynamic(std::size_t pos, Dynamic::Var& val)
|
||||
val = dt;
|
||||
break;
|
||||
}
|
||||
case UUIDOID:
|
||||
{
|
||||
UUID uuid;
|
||||
success = extract(pos, uuid);
|
||||
if (success)
|
||||
val = uuid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
|
@ -94,6 +94,11 @@ Poco::Data::MetaColumn::ColumnDataType oidToColumnDataType(const Oid anOID)
|
||||
cdt = Poco::Data::MetaColumn::FDT_TIMESTAMP;
|
||||
break;
|
||||
|
||||
//uuid
|
||||
case UUIDOID:
|
||||
cdt = Poco::Data::MetaColumn::FDT_BLOB;
|
||||
break;
|
||||
|
||||
// everything else is a string
|
||||
default:
|
||||
cdt = Poco::Data::MetaColumn::FDT_STRING;
|
||||
|
@ -37,6 +37,9 @@ endif
|
||||
ifeq (0, $(shell test -e /opt/postgresql/lib$(LIB64SUFFIX); echo $$?))
|
||||
SYSLIBS += -L/opt/postgresql/lib$(LIB64SUFFIX)
|
||||
endif
|
||||
ifeq (0, $(shell test -e /usr/local/opt/libpq/lib; echo $$?))
|
||||
SYSLIBS += -L/usr/local/opt/libpq/lib$(LIB64SUFFIX)
|
||||
endif
|
||||
|
||||
# Note: linking order is important, do not change it.
|
||||
SYSLIBS += -lpq -lz -lpthread -ldl
|
||||
|
@ -690,6 +690,14 @@ void PostgreSQLTest::testDouble()
|
||||
}
|
||||
|
||||
|
||||
void PostgreSQLTest::testUUID()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
recreateUUIDsTable();
|
||||
_pExecutor->uuids();
|
||||
}
|
||||
|
||||
void PostgreSQLTest::testTuple()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
@ -986,6 +994,15 @@ void PostgreSQLTest::recreateFloatsTable()
|
||||
}
|
||||
|
||||
|
||||
void PostgreSQLTest::recreateUUIDsTable()
|
||||
{
|
||||
dropTable("Strings");
|
||||
try { *_pSession << "CREATE TABLE Strings (str UUID)", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateUUIDsTable()"); }
|
||||
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateUUIDsTable()"); }
|
||||
}
|
||||
|
||||
|
||||
void PostgreSQLTest::recreateTuplesTable()
|
||||
{
|
||||
dropTable("Tuples");
|
||||
@ -1110,6 +1127,7 @@ CppUnit::Test* PostgreSQLTest::suite()
|
||||
CppUnit_addTest(pSuite, PostgreSQLTest, testUnsignedInts);
|
||||
CppUnit_addTest(pSuite, PostgreSQLTest, testFloat);
|
||||
CppUnit_addTest(pSuite, PostgreSQLTest, testDouble);
|
||||
CppUnit_addTest(pSuite, PostgreSQLTest, testUUID);
|
||||
CppUnit_addTest(pSuite, PostgreSQLTest, testTuple);
|
||||
CppUnit_addTest(pSuite, PostgreSQLTest, testTupleVector);
|
||||
CppUnit_addTest(pSuite, PostgreSQLTest, testInternalExtraction);
|
||||
|
@ -82,6 +82,7 @@ public:
|
||||
void testUnsignedInts();
|
||||
void testFloat();
|
||||
void testDouble();
|
||||
void testUUID();
|
||||
|
||||
void testTuple();
|
||||
void testTupleVector();
|
||||
@ -118,6 +119,7 @@ private:
|
||||
void recreateIntsTable();
|
||||
void recreateUnsignedIntsTable();
|
||||
void recreateFloatsTable();
|
||||
void recreateUUIDsTable();
|
||||
void recreateTuplesTable();
|
||||
void recreateVectorsTable();
|
||||
void recreateNullableIntTable();
|
||||
|
@ -712,6 +712,29 @@ void SQLExecutor::floats()
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::uuids()
|
||||
{
|
||||
std::string funct = "uuids()";
|
||||
Poco::UUID data("264a1c6f-7af5-43a5-a593-377aff3d2d7d");
|
||||
Poco::UUID ret;
|
||||
|
||||
try { *_pSession << "INSERT INTO Strings VALUES ($1)", use(data), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||
|
||||
int count = 0;
|
||||
try { *_pSession << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||
assertTrue (count == 1);
|
||||
|
||||
try { *_pSession << "SELECT str FROM Strings", into(ret), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||
assertTrue (ret == data);
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::doubles()
|
||||
{
|
||||
std::string funct = "floats()";
|
||||
@ -1611,7 +1634,7 @@ void SQLExecutor::blobStmt()
|
||||
std::string lastName("lastname");
|
||||
std::string firstName("firstname");
|
||||
std::string address("Address");
|
||||
unsigned char BLOBData[ 10 ] = { 0,1,2,3,4,5,6,7,14,15 };
|
||||
unsigned char BLOBData[ 10 ] = { 0,1,2,3,4,5,6,7,14,15 };
|
||||
Poco::Data::BLOB blob(BLOBData, 10);
|
||||
|
||||
int count = 0;
|
||||
|
@ -89,6 +89,7 @@ public:
|
||||
void unsignedInts();
|
||||
void floats();
|
||||
void doubles();
|
||||
void uuids();
|
||||
void tuples();
|
||||
void tupleVector();
|
||||
|
||||
|
@ -106,6 +106,9 @@ public:
|
||||
void bind(std::size_t pos, const DateTime& val, Direction dir);
|
||||
/// Binds a DateTime.
|
||||
|
||||
void bind(std::size_t pos, const UUID& val, Direction dir);
|
||||
/// Binds a UUID.
|
||||
|
||||
void bind(std::size_t pos, const NullData& val, Direction dir);
|
||||
/// Binds a null.
|
||||
|
||||
|
@ -116,6 +116,9 @@ public:
|
||||
bool extract(std::size_t pos, Poco::DateTime& val);
|
||||
/// Extracts a DateTime.
|
||||
|
||||
bool extract(std::size_t pos, Poco::UUID& val);
|
||||
/// Extracts a Time.
|
||||
|
||||
bool extract(std::size_t pos, Poco::Any& val);
|
||||
/// Extracts an Any.
|
||||
|
||||
@ -264,6 +267,13 @@ private:
|
||||
val = dt;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_UUID:
|
||||
{
|
||||
UUID uuid;
|
||||
ret = extract(pos, uuid);
|
||||
val = uuid;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw Poco::Data::UnknownTypeException("Unknown type during extraction");
|
||||
}
|
||||
|
@ -111,6 +111,13 @@ void Binder::bind(std::size_t pos, const DateTime& val, Direction dir)
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const UUID& val, Direction dir)
|
||||
{
|
||||
std::string str(val.toString());
|
||||
bind(pos, str, dir);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const NullData&, Direction)
|
||||
{
|
||||
sqlite3_bind_null(_pStmt, static_cast<int>(pos));
|
||||
|
@ -208,6 +208,16 @@ bool Extractor::extract(std::size_t pos, DateTime& val)
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, UUID& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
std::string str;
|
||||
extract(pos, str);
|
||||
val.parse(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Any& val)
|
||||
{
|
||||
return extractImpl(pos, val);
|
||||
|
@ -134,6 +134,8 @@ Utility::Utility()
|
||||
_types.insert(TypeMap::value_type("TIME", MetaColumn::FDT_TIME));
|
||||
_types.insert(TypeMap::value_type("DATETIME", MetaColumn::FDT_TIMESTAMP));
|
||||
_types.insert(TypeMap::value_type("TIMESTAMP", MetaColumn::FDT_TIMESTAMP));
|
||||
_types.insert(TypeMap::value_type("UUID", MetaColumn::FDT_UUID));
|
||||
_types.insert(TypeMap::value_type("GUID", MetaColumn::FDT_UUID));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
#include "Poco/Tuple.h"
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/UUIDGenerator.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
#include "Poco/DateTime.h"
|
||||
@ -1916,6 +1917,21 @@ void SQLiteTest::testDateTime()
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testUUID()
|
||||
{
|
||||
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Ids", now;
|
||||
tmp << "CREATE TABLE Ids (id0 UUID)", now;
|
||||
|
||||
Poco::UUID uuid = Poco::UUIDGenerator::defaultGenerator().createRandom();
|
||||
tmp << "INSERT INTO Ids VALUES (?)", use(uuid), now;
|
||||
|
||||
Poco::UUID ruuid;
|
||||
tmp << "SELECT * FROM Ids", into(ruuid), now;
|
||||
assertTrue (ruuid == uuid);
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testInternalExtraction()
|
||||
{
|
||||
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
@ -3453,6 +3469,7 @@ CppUnit::Test* SQLiteTest::suite()
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testTuple1);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testTupleVector1);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testDateTime);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testUUID);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testPrimaryKeyConstraint);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testNullable);
|
||||
|
@ -100,6 +100,8 @@ public:
|
||||
|
||||
void testDateTime();
|
||||
|
||||
void testUUID();
|
||||
|
||||
void testInternalExtraction();
|
||||
void testPrimaryKeyConstraint();
|
||||
void testNullable();
|
||||
|
@ -1022,6 +1022,7 @@ working with a string:
|
||||
|
||||
|
||||
!!!Session Pooling
|
||||
|
||||
Creating a connection to a database is often a time consuming
|
||||
operation. Therefore it makes sense to save a session object for
|
||||
later reuse once it is no longer needed.
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "Poco/Data/LOB.h"
|
||||
#include "Poco/DateTime.h"
|
||||
#include "Poco/Nullable.h"
|
||||
#include "Poco/UUID.h"
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/Dynamic/Var.h"
|
||||
#include "Poco/UTFString.h"
|
||||
@ -317,6 +318,18 @@ public:
|
||||
virtual void bind(std::size_t pos, const std::list<Time>& val, Direction dir = PD_IN);
|
||||
/// Binds a Time list.
|
||||
|
||||
virtual void bind(std::size_t pos, const UUID& val, Direction dir = PD_IN) = 0;
|
||||
/// Binds a UUID.
|
||||
|
||||
virtual void bind(std::size_t pos, const std::vector<UUID>& val, Direction dir = PD_IN);
|
||||
/// Binds a UUID vector.
|
||||
|
||||
virtual void bind(std::size_t pos, const std::deque<UUID>& val, Direction dir = PD_IN);
|
||||
/// Binds a UUID deque.
|
||||
|
||||
virtual void bind(std::size_t pos, const std::list<UUID>& val, Direction dir = PD_IN);
|
||||
/// Binds a UUID list.
|
||||
|
||||
virtual void bind(std::size_t pos, const NullData& val, Direction dir = PD_IN) = 0;
|
||||
/// Binds a null.
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "Poco/Data/Data.h"
|
||||
#include "Poco/Data/Constants.h"
|
||||
#include "Poco/Data/LOB.h"
|
||||
#include "Poco/UUID.h"
|
||||
#include "Poco/UTFString.h"
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
@ -304,6 +305,18 @@ public:
|
||||
virtual bool extract(std::size_t pos, std::list<Time>& val);
|
||||
/// Extracts a Time list.
|
||||
|
||||
virtual bool extract(std::size_t pos, UUID& val) = 0;
|
||||
/// Extracts a UUID. Returns false if null was received.
|
||||
|
||||
virtual bool extract(std::size_t pos, std::vector<UUID>& val);
|
||||
/// Extracts a UUID vector.
|
||||
|
||||
virtual bool extract(std::size_t pos, std::deque<UUID>& val);
|
||||
/// Extracts a UUID deque.
|
||||
|
||||
virtual bool extract(std::size_t pos, std::list<UUID>& val);
|
||||
/// Extracts a UUID list.
|
||||
|
||||
virtual bool extract(std::size_t pos, Any& val) = 0;
|
||||
/// Extracts an Any. Returns false if null was received.
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "Poco/Data/Data.h"
|
||||
#include "Poco/RefCountedObject.h"
|
||||
#include "Poco/Data/LOB.h"
|
||||
#include "Poco/UUID.h"
|
||||
#include "Poco/UTFString.h"
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
@ -310,6 +311,18 @@ public:
|
||||
virtual void prepare(std::size_t pos, const std::list<Time>& val);
|
||||
/// Prepares a Time list.
|
||||
|
||||
virtual void prepare(std::size_t pos, const UUID&) = 0;
|
||||
/// Prepares a UUID.
|
||||
|
||||
virtual void prepare(std::size_t pos, const std::vector<UUID>& val);
|
||||
/// Prepares a UUID vector.
|
||||
|
||||
virtual void prepare(std::size_t pos, const std::deque<UUID>& val);
|
||||
/// Prepares a UUID deque.
|
||||
|
||||
virtual void prepare(std::size_t pos, const std::list<UUID>& val);
|
||||
/// Prepares a UUID list.
|
||||
|
||||
virtual void prepare(std::size_t pos, const Any&) = 0;
|
||||
/// Prepares an Any.
|
||||
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
FDT_DATE,
|
||||
FDT_TIME,
|
||||
FDT_TIMESTAMP,
|
||||
FDT_UUID,
|
||||
FDT_UNKNOWN
|
||||
};
|
||||
|
||||
|
@ -404,6 +404,24 @@ void AbstractBinder::bind(std::size_t pos, const std::list<Time>& val, Direction
|
||||
}
|
||||
|
||||
|
||||
void AbstractBinder::bind(std::size_t pos, const std::vector<UUID>& val, Direction dir)
|
||||
{
|
||||
throw NotImplementedException("std::vector binder must be implemented.");
|
||||
}
|
||||
|
||||
|
||||
void AbstractBinder::bind(std::size_t pos, const std::deque<UUID>& val, Direction dir)
|
||||
{
|
||||
throw NotImplementedException("std::deque binder must be implemented.");
|
||||
}
|
||||
|
||||
|
||||
void AbstractBinder::bind(std::size_t pos, const std::list<UUID>& val, Direction dir)
|
||||
{
|
||||
throw NotImplementedException("std::list binder must be implemented.");
|
||||
}
|
||||
|
||||
|
||||
void AbstractBinder::bind(std::size_t pos, const std::vector<NullData>& val, Direction dir)
|
||||
{
|
||||
throw NotImplementedException("std::vector binder must be implemented.");
|
||||
|
@ -398,6 +398,24 @@ bool AbstractExtractor::extract(std::size_t pos, std::list<Time>& val)
|
||||
}
|
||||
|
||||
|
||||
bool AbstractExtractor::extract(std::size_t pos, std::vector<UUID>& val)
|
||||
{
|
||||
throw NotImplementedException("std::vector extractor must be implemented.");
|
||||
}
|
||||
|
||||
|
||||
bool AbstractExtractor::extract(std::size_t pos, std::deque<UUID>& val)
|
||||
{
|
||||
throw NotImplementedException("std::deque extractor must be implemented.");
|
||||
}
|
||||
|
||||
|
||||
bool AbstractExtractor::extract(std::size_t pos, std::list<UUID>& val)
|
||||
{
|
||||
throw NotImplementedException("std::list extractor must be implemented.");
|
||||
}
|
||||
|
||||
|
||||
bool AbstractExtractor::extract(std::size_t pos, std::vector<Any>& val)
|
||||
{
|
||||
throw NotImplementedException("std::vector extractor must be implemented.");
|
||||
|
@ -399,6 +399,24 @@ void AbstractPreparator::prepare(std::size_t pos, const std::list<Time>& val)
|
||||
}
|
||||
|
||||
|
||||
void AbstractPreparator::prepare(std::size_t pos, const std::vector<UUID>& val)
|
||||
{
|
||||
throw NotImplementedException("std::vector preparator must be implemented.");
|
||||
}
|
||||
|
||||
|
||||
void AbstractPreparator::prepare(std::size_t pos, const std::deque<UUID>& val)
|
||||
{
|
||||
throw NotImplementedException("std::deque preparator must be implemented.");
|
||||
}
|
||||
|
||||
|
||||
void AbstractPreparator::prepare(std::size_t pos, const std::list<UUID>& val)
|
||||
{
|
||||
throw NotImplementedException("std::list preparator must be implemented.");
|
||||
}
|
||||
|
||||
|
||||
void AbstractPreparator::prepare(std::size_t pos, const std::vector<Any>& val)
|
||||
{
|
||||
throw NotImplementedException("std::vector preparator must be implemented.");
|
||||
|
@ -159,6 +159,7 @@ Poco::Dynamic::Var RecordSet::value(std::size_t col, std::size_t row, bool useFi
|
||||
case MetaColumn::FDT_DATE: return value<Date>(col, row, useFilter);
|
||||
case MetaColumn::FDT_TIME: return value<Time>(col, row, useFilter);
|
||||
case MetaColumn::FDT_TIMESTAMP: return value<DateTime>(col, row);
|
||||
case MetaColumn::FDT_UUID: return value<UUID>(col, row);
|
||||
default:
|
||||
throw UnknownTypeException("Data type not supported.");
|
||||
}
|
||||
@ -192,6 +193,7 @@ Poco::Dynamic::Var RecordSet::value(const std::string& name, std::size_t row, bo
|
||||
case MetaColumn::FDT_DATE: return value<Date>(name, row, useFilter);
|
||||
case MetaColumn::FDT_TIME: return value<Time>(name, row, useFilter);
|
||||
case MetaColumn::FDT_TIMESTAMP: return value<DateTime>(name, row, useFilter);
|
||||
case MetaColumn::FDT_UUID: return value<UUID>(name, row, useFilter);
|
||||
default:
|
||||
throw UnknownTypeException("Data type not supported.");
|
||||
}
|
||||
|
@ -351,6 +351,8 @@ void StatementImpl::makeExtractors(std::size_t count)
|
||||
addInternalExtract<Time>(mc); break;
|
||||
case MetaColumn::FDT_TIMESTAMP:
|
||||
addInternalExtract<DateTime>(mc); break;
|
||||
case MetaColumn::FDT_UUID:
|
||||
addInternalExtract<UUID>(mc); break;
|
||||
default:
|
||||
throw Poco::InvalidArgumentException("Data type not supported.");
|
||||
}
|
||||
|
@ -140,6 +140,11 @@ void Binder::bind(std::size_t pos, const DateTime& val, Direction dir)
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const UUID& val, Direction dir)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const NullData& val, Direction dir)
|
||||
{
|
||||
}
|
||||
|
@ -100,8 +100,11 @@ public:
|
||||
void bind(std::size_t pos, const DateTime& val, Direction dir);
|
||||
/// Binds a DateTime.
|
||||
|
||||
void bind(std::size_t pos, const UUID& val, Direction dir);
|
||||
/// Binds a UUID.
|
||||
|
||||
void bind(std::size_t pos, const NullData& val, Direction dir);
|
||||
/// Binds a DateTime.
|
||||
/// Binds a NullData.
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
@ -166,13 +166,18 @@ bool Extractor::extract(std::size_t pos, Poco::Data::Time& val)
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::DateTime& val)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::UUID& val)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Any& val)
|
||||
{
|
||||
return true;
|
||||
|
@ -100,9 +100,12 @@ public:
|
||||
bool extract(std::size_t pos, Time& val);
|
||||
/// Extracts a Time.
|
||||
|
||||
bool extract(std::size_t pos, Poco::DateTime& val);
|
||||
bool extract(std::size_t pos, DateTime& val);
|
||||
/// Extracts a DateTime.
|
||||
|
||||
bool extract(std::size_t pos, UUID& val);
|
||||
/// Extracts a UUID.
|
||||
|
||||
bool isNull(std::size_t col, std::size_t row = -1);
|
||||
/// Returns true if the current row value at pos column is null.
|
||||
|
||||
|
@ -135,6 +135,11 @@ void Preparator::prepare(std::size_t pos, const Poco::DateTime&)
|
||||
}
|
||||
|
||||
|
||||
void Preparator::prepare(std::size_t pos, const Poco::UUID&)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Preparator::prepare(std::size_t pos, const Poco::Any&)
|
||||
{
|
||||
}
|
||||
|
@ -98,6 +98,9 @@ public:
|
||||
void prepare(std::size_t pos, const Poco::DateTime&);
|
||||
/// Prepares a DateTime.
|
||||
|
||||
void prepare(std::size_t pos, const Poco::UUID&);
|
||||
/// Prepares a UUID.
|
||||
|
||||
void prepare(std::size_t pos, const Poco::Any&);
|
||||
/// Prepares an Any.
|
||||
|
||||
|
@ -523,6 +523,9 @@ public:
|
||||
bool isDateTime() const;
|
||||
/// Returns true if stored value represents a date/time.
|
||||
|
||||
bool isUUID() const;
|
||||
/// Returns true if stored value is a Poco::UUID.
|
||||
|
||||
std::size_t size() const;
|
||||
/// Returns the size of this Var.
|
||||
/// This function returns 0 when Var is empty, 1 for POD or the size (i.e. length)
|
||||
@ -896,6 +899,13 @@ inline bool Var::isDateTime() const
|
||||
}
|
||||
|
||||
|
||||
inline bool Var::isUUID() const
|
||||
{
|
||||
VarHolder* pHolder = content();
|
||||
return pHolder ? pHolder->isUUID() : false;
|
||||
}
|
||||
|
||||
|
||||
inline std::size_t Var::size() const
|
||||
{
|
||||
VarHolder* pHolder = content();
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "Poco/UnicodeConverter.h"
|
||||
#include "Poco/UTFString.h"
|
||||
#include "Poco/UTF8String.h"
|
||||
#include "Poco/UUID.h"
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include <vector>
|
||||
@ -178,6 +179,10 @@ public:
|
||||
/// Throws BadCastException. Must be overridden in a type
|
||||
/// specialization in order to support the conversion.
|
||||
|
||||
virtual void convert(UUID& val) const;
|
||||
/// Throws BadCastException. Must be overridden in a type
|
||||
/// specialization in order to support the conversion.
|
||||
|
||||
#ifndef POCO_INT64_IS_LONG
|
||||
|
||||
void convert(long& val) const;
|
||||
@ -277,6 +282,10 @@ public:
|
||||
/// Returns false. Must be properly overridden in a type
|
||||
/// specialization in order to support the diagnostic.
|
||||
|
||||
virtual bool isUUID() const;
|
||||
/// Returns false. Must be properly overridden in a type
|
||||
/// specialization in order to support the diagnostic.
|
||||
|
||||
virtual std::size_t size() const;
|
||||
/// Returns 1 iff Var is not empty or this function overridden.
|
||||
|
||||
@ -519,8 +528,16 @@ inline void VarHolder::convert(Timestamp& /*val*/) const
|
||||
throw BadCastException("Can not convert to Timestamp");
|
||||
}
|
||||
|
||||
|
||||
inline void VarHolder::convert(UUID& /*val*/) const
|
||||
{
|
||||
throw BadCastException("Can not convert to UUID");
|
||||
}
|
||||
|
||||
|
||||
#ifndef POCO_INT64_IS_LONG
|
||||
|
||||
|
||||
inline void VarHolder::convert(long& val) const
|
||||
{
|
||||
Int32 tmp;
|
||||
@ -536,8 +553,10 @@ inline void VarHolder::convert(unsigned long& val) const
|
||||
val = tmp;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
inline void VarHolder::convert(long long& /*val*/) const
|
||||
{
|
||||
throw BadCastException("Can not convert to long long");
|
||||
@ -549,8 +568,10 @@ inline void VarHolder::convert(unsigned long long& /*val*/) const
|
||||
throw BadCastException("Can not convert to unsigned long long");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
inline void VarHolder::convert(bool& /*val*/) const
|
||||
{
|
||||
throw BadCastException("Can not convert to bool");
|
||||
@ -671,6 +692,12 @@ inline bool VarHolder::isDateTime() const
|
||||
}
|
||||
|
||||
|
||||
inline bool VarHolder::isUUID() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
inline std::size_t VarHolder::size() const
|
||||
{
|
||||
return 1u;
|
||||
@ -1026,7 +1053,6 @@ public:
|
||||
return std::numeric_limits<Int16>::is_specialized;
|
||||
}
|
||||
|
||||
|
||||
bool isString() const
|
||||
{
|
||||
return false;
|
||||
@ -2750,6 +2776,11 @@ public:
|
||||
ts = tmp.timestamp();
|
||||
}
|
||||
|
||||
void convert(UUID& uuid) const
|
||||
{
|
||||
uuid.parse(_val);
|
||||
}
|
||||
|
||||
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
|
||||
{
|
||||
return cloneHolder(pVarHolder, _val);
|
||||
@ -3917,6 +3948,11 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isUUID() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
VarHolderImpl();
|
||||
VarHolderImpl(const VarHolderImpl&);
|
||||
@ -4047,6 +4083,11 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isUUID() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
VarHolderImpl();
|
||||
VarHolderImpl(const VarHolderImpl&);
|
||||
@ -4177,6 +4218,11 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isUUID() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
VarHolderImpl();
|
||||
VarHolderImpl(const VarHolderImpl&);
|
||||
@ -4186,6 +4232,102 @@ private:
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
class VarHolderImpl<UUID>: public VarHolder
|
||||
{
|
||||
public:
|
||||
VarHolderImpl(const UUID& val): _val(val)
|
||||
{
|
||||
}
|
||||
|
||||
~VarHolderImpl()
|
||||
{
|
||||
}
|
||||
|
||||
const std::type_info& type() const
|
||||
{
|
||||
return typeid(UUID);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
{
|
||||
val = _val.toString();
|
||||
}
|
||||
|
||||
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
|
||||
{
|
||||
return cloneHolder(pVarHolder, _val);
|
||||
}
|
||||
|
||||
const UUID& value() const
|
||||
{
|
||||
return _val;
|
||||
}
|
||||
|
||||
bool isArray() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isStruct() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isInteger() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSigned() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isNumeric() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isBoolean() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isString() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isDate() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isTime() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isDateTime() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isUUID() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
VarHolderImpl();
|
||||
VarHolderImpl(const VarHolderImpl&);
|
||||
VarHolderImpl& operator = (const VarHolderImpl&);
|
||||
|
||||
Poco::UUID _val;
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<Var> Vector;
|
||||
typedef std::deque<Var> Deque;
|
||||
typedef std::list<Var> List;
|
||||
|
@ -47,7 +47,8 @@ bool isJSONString(const Var& any)
|
||||
any.type() == typeid(char*) ||
|
||||
any.type() == typeid(Poco::DateTime) ||
|
||||
any.type() == typeid(Poco::LocalDateTime) ||
|
||||
any.type() == typeid(Poco::Timestamp);
|
||||
any.type() == typeid(Poco::Timestamp) ||
|
||||
any.type() == typeid(Poco::UUID);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2859,6 +2859,32 @@ void VarTest::testDate()
|
||||
}
|
||||
|
||||
|
||||
void VarTest::testUUID()
|
||||
{
|
||||
Poco::UUID uuid("f1881be4-c3b7-4a47-9619-5169db5108a7");
|
||||
|
||||
Var vuuid(uuid);
|
||||
assertTrue (vuuid.isUUID());
|
||||
|
||||
assert (vuuid.convert<std::string>() == "f1881be4-c3b7-4a47-9619-5169db5108a7");
|
||||
|
||||
assert (vuuid.extract<Poco::UUID>() == uuid);
|
||||
|
||||
Var vstr(std::string("f1881be4-c3b7-4a47-9619-5169db5108a7"));
|
||||
assert (vstr.convert<Poco::UUID>() == uuid);
|
||||
|
||||
Var vstr2(std::string("notAnUUID"));
|
||||
try
|
||||
{
|
||||
Poco::UUID uuid2 = vstr2.convert<Poco::UUID>();
|
||||
fail("not a valid UUID, must fail");
|
||||
}
|
||||
catch (Poco::SyntaxException&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VarTest::testGetIdxNoThrow(Var& a1, std::vector<Var>::size_type n)
|
||||
{
|
||||
Var val1 = a1[n];
|
||||
@ -3104,6 +3130,7 @@ CppUnit::Test* VarTest::suite()
|
||||
CppUnit_addTest(pSuite, VarTest, testJSONDeserializeComplex);
|
||||
CppUnit_addTest(pSuite, VarTest, testJSONRoundtripStruct);
|
||||
CppUnit_addTest(pSuite, VarTest, testDate);
|
||||
CppUnit_addTest(pSuite, VarTest, testUUID);
|
||||
CppUnit_addTest(pSuite, VarTest, testEmpty);
|
||||
CppUnit_addTest(pSuite, VarTest, testIterator);
|
||||
|
||||
|
@ -74,10 +74,10 @@ public:
|
||||
void testJSONRoundtripStruct();
|
||||
void testJSONDeserializeComplex();
|
||||
void testDate();
|
||||
void testUUID();
|
||||
void testEmpty();
|
||||
void testIterator();
|
||||
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
static CppUnit::Test* suite();
|
||||
|
Loading…
Reference in New Issue
Block a user