mirror of
https://github.com/pocoproject/poco.git
synced 2025-03-27 00:35:23 +01:00
Changes related to following tracker items:
[2025916] ODBC binds empty string as null? [2000408] DynamicAny non-initialized state support [1981130] pointless comparison of unsigned integer with zero and some refactoring. Warning: only tested on Windows.
This commit is contained in:
parent
3e65280dc1
commit
fc5a503593
@ -79,7 +79,7 @@ public:
|
||||
typedef std::vector<DiagnosticFields> FieldVec;
|
||||
typedef typename FieldVec::const_iterator Iterator;
|
||||
|
||||
explicit Diagnostics(H& rHandle): _rHandle(rHandle)
|
||||
explicit Diagnostics(const H& handle): _handle(handle)
|
||||
/// Creates and initializes the Diagnostics.
|
||||
{
|
||||
std::memset(_connectionName, 0, sizeof(_connectionName));
|
||||
@ -169,7 +169,7 @@ public:
|
||||
reset();
|
||||
|
||||
while (!Utility::isError(SQLGetDiagRec(handleType,
|
||||
_rHandle,
|
||||
_handle,
|
||||
count,
|
||||
df._sqlState,
|
||||
&df._nativeError,
|
||||
@ -183,7 +183,7 @@ public:
|
||||
// (they fail if connection has not been established yet
|
||||
// or return empty string if not applicable for the context)
|
||||
if (Utility::isError(SQLGetDiagField(handleType,
|
||||
_rHandle,
|
||||
_handle,
|
||||
count,
|
||||
SQL_DIAG_CONNECTION_NAME,
|
||||
_connectionName,
|
||||
@ -202,7 +202,7 @@ public:
|
||||
}
|
||||
|
||||
if (Utility::isError(SQLGetDiagField(handleType,
|
||||
_rHandle,
|
||||
_handle,
|
||||
count,
|
||||
SQL_DIAG_SERVER_NAME,
|
||||
_serverName,
|
||||
@ -245,7 +245,7 @@ private:
|
||||
FieldVec _fields;
|
||||
|
||||
/// Context handle
|
||||
H& _rHandle;
|
||||
const H& _handle;
|
||||
};
|
||||
|
||||
|
||||
|
@ -63,7 +63,7 @@ class Error
|
||||
/// as well as individual diagnostic records.
|
||||
{
|
||||
public:
|
||||
explicit Error(H handle) : _diagnostics(handle)
|
||||
explicit Error(const H& handle) : _diagnostics(handle)
|
||||
/// Creates the Error.
|
||||
{
|
||||
}
|
||||
|
@ -47,6 +47,8 @@
|
||||
#include "Poco/Data/ODBC/ODBCMetaColumn.h"
|
||||
#include "Poco/Data/ODBC/Error.h"
|
||||
#include "Poco/Data/ODBC/Utility.h"
|
||||
#include "Poco/Data/Date.h"
|
||||
#include "Poco/Data/Time.h"
|
||||
#include "Poco/DateTime.h"
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
@ -398,6 +400,15 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, typename NT>
|
||||
bool extAny(std::size_t pos, T& val)
|
||||
{
|
||||
NT i;
|
||||
extract(pos, i);
|
||||
val = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool extractImpl(std::size_t pos, T& val)
|
||||
/// Utility function for extraction of Any and DynamicAny.
|
||||
@ -407,46 +418,52 @@ private:
|
||||
switch (column.type())
|
||||
{
|
||||
case MetaColumn::FDT_INT8:
|
||||
{ Poco::Int8 i = 0; extract(pos, i); val = i; return true; }
|
||||
{ return extAny<T, Poco::Int8>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_UINT8:
|
||||
{ Poco::UInt8 i = 0; extract(pos, i); val = i; return true; }
|
||||
{ return extAny<T, Poco::UInt8>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_INT16:
|
||||
{ Poco::Int16 i = 0; extract(pos, i); val = i; return true; }
|
||||
{ return extAny<T, Poco::Int16>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_UINT16:
|
||||
{ Poco::UInt16 i = 0; extract(pos, i); val = i; return true; }
|
||||
{ return extAny<T, Poco::UInt16>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_INT32:
|
||||
{ Poco::Int32 i = 0; extract(pos, i); val = i; return true; }
|
||||
{ return extAny<T, Poco::Int32>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_UINT32:
|
||||
{ Poco::UInt32 i = 0; extract(pos, i); val = i; return true; }
|
||||
{ return extAny<T, Poco::UInt32>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_INT64:
|
||||
{ Poco::Int64 i = 0; extract(pos, i); val = i; return true; }
|
||||
{ return extAny<T, Poco::Int64>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_UINT64:
|
||||
{ Poco::UInt64 i = 0; extract(pos, i); val = i; return true; }
|
||||
{ return extAny<T, Poco::UInt64>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_BOOL:
|
||||
{ bool b; extract(pos, b); val = b; return true; }
|
||||
{ return extAny<T, bool>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_FLOAT:
|
||||
{ float f; extract(pos, f); val = f; return true; }
|
||||
{ return extAny<T, float>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_DOUBLE:
|
||||
{ double d; extract(pos, d); val = d; return true; }
|
||||
{ return extAny<T, double>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_STRING:
|
||||
{ std::string s; extract(pos, s); val = s; return true; }
|
||||
{ return extAny<T, std::string>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_BLOB:
|
||||
{ Poco::Data::BLOB b; extract(pos, b); val = b; return true; }
|
||||
{ return extAny<T, Poco::Data::BLOB>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_DATE:
|
||||
{ return extAny<T, Poco::Data::Date>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_TIME:
|
||||
{ return extAny<T, Poco::Data::Time>(pos, val); }
|
||||
|
||||
case MetaColumn::FDT_TIMESTAMP:
|
||||
{ Poco::DateTime b; extract(pos, b); val = b; return true; }
|
||||
{ return extAny<T, Poco::DateTime>(pos, val); }
|
||||
|
||||
default:
|
||||
throw DataFormatException("Unsupported data type.");
|
||||
|
@ -128,22 +128,17 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
||||
}
|
||||
else if (isInBound(dir))
|
||||
{
|
||||
if (size) pVal = (SQLPOINTER) val.c_str();
|
||||
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;
|
||||
if (0 != size) *pLenIn = SQL_NTS;
|
||||
else
|
||||
{
|
||||
*pLenIn = SQL_NULL_DATA;
|
||||
SQLINTEGER colSize = 0;
|
||||
SQLSMALLINT decDigits = 0;
|
||||
getColSizeAndPrecision(pos, SQL_C_CHAR, colSize, decDigits);
|
||||
size = colSize;
|
||||
}
|
||||
SQLINTEGER colSize = 0;
|
||||
SQLSMALLINT decDigits = 0;
|
||||
getColSizeAndPrecision(pos, SQL_C_CHAR, colSize, decDigits);
|
||||
*pLenIn = SQL_NTS;
|
||||
|
||||
if (PB_AT_EXEC == _paramBinding)
|
||||
*pLenIn = SQL_LEN_DATA_AT_EXEC(size);
|
||||
@ -155,7 +150,7 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
||||
toODBCDirection(dir),
|
||||
SQL_C_CHAR,
|
||||
SQL_LONGVARCHAR,
|
||||
(SQLUINTEGER) size,
|
||||
(SQLUINTEGER) colSize,
|
||||
0,
|
||||
pVal,
|
||||
(SQLINTEGER) size,
|
||||
@ -177,16 +172,7 @@ void Binder::bind(std::size_t pos, const BLOB& val, Direction dir)
|
||||
_inParams.insert(ParamMap::value_type(pVal, size));
|
||||
|
||||
SQLLEN* pLenIn = new SQLLEN;
|
||||
|
||||
if (0 != size) *pLenIn = size;
|
||||
else
|
||||
{
|
||||
*pLenIn = SQL_NULL_DATA;
|
||||
SQLINTEGER colSize = 0;
|
||||
SQLSMALLINT decDigits = 0;
|
||||
getColSizeAndPrecision(pos, SQL_C_CHAR, colSize, decDigits);
|
||||
size = colSize;
|
||||
}
|
||||
*pLenIn = size;
|
||||
|
||||
if (PB_AT_EXEC == _paramBinding)
|
||||
*pLenIn = SQL_LEN_DATA_AT_EXEC(size);
|
||||
@ -200,7 +186,7 @@ void Binder::bind(std::size_t pos, const BLOB& val, Direction dir)
|
||||
SQL_LONGVARBINARY,
|
||||
(SQLUINTEGER) size,
|
||||
0,
|
||||
pVal,
|
||||
pVal,
|
||||
(SQLINTEGER) size,
|
||||
_lengthIndicator.back())))
|
||||
{
|
||||
|
@ -1274,8 +1274,8 @@ bool Extractor::isNull(std::size_t col, std::size_t row)
|
||||
try
|
||||
{
|
||||
return isNullLengthIndicator(_lengths.at(col));
|
||||
}catch (std::out_of_range& ex)
|
||||
{
|
||||
} catch (std::out_of_range& ex)
|
||||
{
|
||||
throw RangeException(ex.what());
|
||||
}
|
||||
}
|
||||
|
@ -242,12 +242,19 @@ void ODBCStatementImpl::putData()
|
||||
|
||||
while (SQL_NEED_DATA == (rc = SQLParamData(_stmt, &pParam)))
|
||||
{
|
||||
poco_assert_dbg (pParam);
|
||||
dataSize = (SQLINTEGER) _pBinder->parameterSize(pParam);
|
||||
if (pParam)
|
||||
{
|
||||
dataSize = (SQLINTEGER) _pBinder->parameterSize(pParam);
|
||||
|
||||
if (Utility::isError(SQLPutData(_stmt, pParam, dataSize)))
|
||||
throw StatementException(_stmt, "SQLPutData()");
|
||||
|
||||
if (Utility::isError(SQLPutData(_stmt, pParam, dataSize)))
|
||||
throw StatementException(_stmt, "SQLPutData()");
|
||||
}
|
||||
else // if pParam is null pointer, do a dummy call
|
||||
{
|
||||
char dummy = 0;
|
||||
if (Utility::isError(SQLPutData(_stmt, &dummy, 0)))
|
||||
throw StatementException(_stmt, "SQLPutData()");
|
||||
}
|
||||
}
|
||||
|
||||
checkError(rc, "SQLParamData()");
|
||||
|
@ -80,7 +80,7 @@ Utility::DriverMap& Utility::drivers(Utility::DriverMap& driverMap)
|
||||
}
|
||||
|
||||
if (SQL_NO_DATA != rc)
|
||||
throw EnvironmentError(henv);
|
||||
throw EnvironmentException(henv);
|
||||
|
||||
return driverMap;
|
||||
}
|
||||
@ -116,7 +116,7 @@ Utility::DSNMap& Utility::dataSources(Utility::DSNMap& dsnMap)
|
||||
}
|
||||
|
||||
if (SQL_NO_DATA != rc)
|
||||
throw EnvironmentError(henv);
|
||||
throw EnvironmentException(henv);
|
||||
|
||||
return dsnMap;
|
||||
}
|
||||
|
@ -2682,10 +2682,10 @@ void SQLExecutor::nulls()
|
||||
assert (1 == rs.rowCount());
|
||||
rs.moveFirst();
|
||||
assert (rs.isNull("i"));
|
||||
assert (rs["i"] == 0);
|
||||
assert (rs["i"] != 0);
|
||||
assert (rs.isNull("r"));
|
||||
assert (rs.isNull("v"));
|
||||
assert (rs["v"] == "");
|
||||
assert (rs["v"] != "");
|
||||
try { session() << "DELETE FROM NullTest", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
@ -2721,14 +2721,57 @@ void SQLExecutor::nulls()
|
||||
assert (rs["i"] == 1);
|
||||
assert (!rs.isNull("r"));
|
||||
assert (rs.isNull("v"));
|
||||
assert (rs["v"] == "");
|
||||
assert (rs["v"] != "");
|
||||
|
||||
assert (rs.moveNext());
|
||||
assert (!rs.isNull("i"));
|
||||
assert (rs["i"] == 2);
|
||||
assert (rs.isNull("r"));
|
||||
assert (rs.isNull("v"));
|
||||
assert (rs["v"] == "");
|
||||
assert (rs["v"] != "");
|
||||
|
||||
try { session() << "DELETE FROM NullTest", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
|
||||
try { session() << "INSERT INTO NullTest (v) VALUES (?)", bind(""), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
|
||||
bool esin = session().getFeature("emptyStringIsNull");
|
||||
session().setFeature("emptyStringIsNull", true);
|
||||
|
||||
try
|
||||
{
|
||||
session().setFeature("forceEmptyString", true);
|
||||
fail ("must fail");
|
||||
} catch (InvalidAccessException&) { }
|
||||
|
||||
bool fes = session().getFeature("forceEmptyString");
|
||||
session().setFeature("forceEmptyString", false);
|
||||
|
||||
RecordSet rs1(session(), "SELECT v FROM NullTest");
|
||||
assert (1 == rs1.rowCount());
|
||||
rs1.moveFirst();
|
||||
assert (rs1.isNull("v"));
|
||||
assert (!(rs["v"] == ""));
|
||||
|
||||
session().setFeature("emptyStringIsNull", false);
|
||||
session().setFeature("forceEmptyString", true);
|
||||
RecordSet rs2(session(), "SELECT v FROM NullTest");
|
||||
assert (1 == rs2.rowCount());
|
||||
rs2.moveFirst();
|
||||
assert (!rs2.isNull("v"));
|
||||
assert ((rs2["v"] == ""));
|
||||
|
||||
try
|
||||
{
|
||||
session().setFeature("emptyStringIsNull", true);
|
||||
fail ("must fail");
|
||||
} catch (InvalidAccessException&) { }
|
||||
|
||||
session().setFeature("emptyStringIsNull", esin);
|
||||
session().setFeature("forceEmptyString", fes);
|
||||
}
|
||||
|
||||
|
||||
|
@ -129,11 +129,44 @@ public:
|
||||
bool isBulk() const;
|
||||
/// Returns true if this is bulk extraction.
|
||||
|
||||
void setEmptyStringIsNull(bool emptyStringIsNull);
|
||||
/// Sets the empty string handling flag.
|
||||
|
||||
bool getEmptyStringIsNull() const;
|
||||
/// Returns the empty string handling flag.
|
||||
|
||||
void setForceEmptyString(bool forceEmptyString);
|
||||
/// Sets the force empty string flag.
|
||||
|
||||
bool getForceEmptyString() const;
|
||||
/// Returns the force empty string flag.
|
||||
|
||||
template <typename T>
|
||||
bool isValueNull(const T& str, bool deflt)
|
||||
/// Utility function to determine the nullness of the value.
|
||||
/// This generic version always returns default value
|
||||
/// (i.e. does nothing).
|
||||
///
|
||||
{
|
||||
return deflt;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool isValueNull(const std::string& str, bool deflt);
|
||||
/// Specialization for const reference to std::string.
|
||||
///
|
||||
/// Returns true when folowing conditions are met:
|
||||
///
|
||||
/// - string is empty
|
||||
/// - getEmptyStringIsNull() returns true
|
||||
|
||||
private:
|
||||
AbstractExtractor* _pExtractor;
|
||||
Poco::UInt32 _limit;
|
||||
Poco::UInt32 _position;
|
||||
bool _bulk;
|
||||
bool _emptyStringIsNull;
|
||||
bool _forceEmptyString;
|
||||
};
|
||||
|
||||
|
||||
@ -202,6 +235,30 @@ inline bool AbstractExtraction::canExtract() const
|
||||
}
|
||||
|
||||
|
||||
inline void AbstractExtraction::setEmptyStringIsNull(bool emptyStringIsNull)
|
||||
{
|
||||
_emptyStringIsNull = emptyStringIsNull;
|
||||
}
|
||||
|
||||
|
||||
inline bool AbstractExtraction::getEmptyStringIsNull() const
|
||||
{
|
||||
return _emptyStringIsNull;
|
||||
}
|
||||
|
||||
|
||||
inline void AbstractExtraction::setForceEmptyString(bool forceEmptyString)
|
||||
{
|
||||
_forceEmptyString = forceEmptyString;
|
||||
}
|
||||
|
||||
|
||||
inline bool AbstractExtraction::getForceEmptyString() const
|
||||
{
|
||||
return _forceEmptyString;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
|
||||
|
@ -72,7 +72,10 @@ public:
|
||||
typedef Poco::Any (C::*PropertyGetter)(const std::string&);
|
||||
/// The getter method for a property.
|
||||
|
||||
AbstractSessionImpl()
|
||||
AbstractSessionImpl(): _storage(std::string("deque")),
|
||||
_bulk(false),
|
||||
_emptyStringIsNull(false),
|
||||
_forceEmptyString(false)
|
||||
/// Creates the AbstractSessionImpl.
|
||||
///
|
||||
/// Adds "storage" property and sets the default internal storage container
|
||||
@ -83,22 +86,41 @@ public:
|
||||
/// duration of the session) and locally (for a single statement execution only).
|
||||
/// See StatementImpl for details on how this property is used at runtime.
|
||||
///
|
||||
/// Adds bulk feature and sets it to false.
|
||||
/// Adds "bulk" feature and sets it to false.
|
||||
/// Bulk feature determines whether the session is capable of bulk operations.
|
||||
/// Connectors that are capable of it must set this feature prior to attempting
|
||||
/// bulk operations.
|
||||
///
|
||||
/// Adds "emptyStringIsNull" feature and sets it to false. This feature should be
|
||||
/// set to true in order to modify the behavior of the databases that distinguish
|
||||
/// between zero-length character strings as nulls. Setting this feature to true
|
||||
/// shall disregard any difference between empty character strings and nulls,
|
||||
/// causing the framework to treat them the same (i.e. behave like Oracle).
|
||||
///
|
||||
/// Adds "forceEmptyString" feature and sets it to false. This feature should be set
|
||||
/// to true in order to force the databases that do not distinguish empty strings from
|
||||
/// nulls (e.g. Oracle) to always report empty string.
|
||||
///
|
||||
/// The "emptyStringIsNull" and "forceEmptyString" features are mutually exclusive.
|
||||
/// While these features can not both be true at the same time, they can both be false,
|
||||
/// resulting in default underlying database behavior.
|
||||
///
|
||||
{
|
||||
addProperty("storage",
|
||||
&AbstractSessionImpl<C>::setStorage,
|
||||
&AbstractSessionImpl<C>::getStorage);
|
||||
|
||||
setProperty("storage", std::string("deque"));
|
||||
|
||||
addFeature("bulk",
|
||||
&AbstractSessionImpl<C>::setBulk,
|
||||
&AbstractSessionImpl<C>::getBulk);
|
||||
|
||||
setFeature("bulk", false);
|
||||
addFeature("emptyStringIsNull",
|
||||
&AbstractSessionImpl<C>::setEmptyStringIsNull,
|
||||
&AbstractSessionImpl<C>::getEmptyStringIsNull);
|
||||
|
||||
addFeature("forceEmptyString",
|
||||
&AbstractSessionImpl<C>::setForceEmptyString,
|
||||
&AbstractSessionImpl<C>::getForceEmptyString);
|
||||
}
|
||||
|
||||
~AbstractSessionImpl()
|
||||
@ -196,6 +218,47 @@ public:
|
||||
return _bulk;
|
||||
}
|
||||
|
||||
void setEmptyStringIsNull(const std::string& name, bool emptyStringIsNull)
|
||||
/// Sets the behavior regarding empty variable length strings.
|
||||
/// Those are treated as NULL by Oracle and as empty string by
|
||||
/// most other databases.
|
||||
/// When this feature is true, empty strings are treated as NULL.
|
||||
{
|
||||
if (emptyStringIsNull && _forceEmptyString)
|
||||
throw InvalidAccessException("Features mutually exclusive");
|
||||
|
||||
_emptyStringIsNull = emptyStringIsNull;
|
||||
}
|
||||
|
||||
bool getEmptyStringIsNull(const std::string& name="")
|
||||
/// Returns the setting for the behavior regarding empty variable
|
||||
/// length strings. See setEmptyStringIsNull(const std::string&, bool)
|
||||
/// and this class documentation for feature rationale and details.
|
||||
{
|
||||
return _emptyStringIsNull;
|
||||
}
|
||||
|
||||
void setForceEmptyString(const std::string& name, bool forceEmptyString)
|
||||
/// Sets the behavior regarding empty variable length strings.
|
||||
/// Those are treated as NULL by Oracle and as empty string by
|
||||
/// most other databases.
|
||||
/// When this feature is true, both empty strings and NULL values
|
||||
/// are reported as empty strings.
|
||||
{
|
||||
if (forceEmptyString && _emptyStringIsNull)
|
||||
throw InvalidAccessException("Features mutually exclusive");
|
||||
|
||||
_forceEmptyString = forceEmptyString;
|
||||
}
|
||||
|
||||
bool getForceEmptyString(const std::string& name="")
|
||||
/// Returns the setting for the behavior regarding empty variable
|
||||
/// length strings. See setForceEmptyString(const std::string&, bool)
|
||||
/// and this class documentation for feature rationale and details.
|
||||
{
|
||||
return _forceEmptyString;
|
||||
}
|
||||
|
||||
protected:
|
||||
void addFeature(const std::string& name, FeatureSetter setter, FeatureGetter getter)
|
||||
/// Adds a feature to the map of supported features.
|
||||
@ -241,6 +304,8 @@ private:
|
||||
PropertyMap _properties;
|
||||
std::string _storage;
|
||||
bool _bulk;
|
||||
bool _emptyStringIsNull;
|
||||
bool _forceEmptyString;
|
||||
};
|
||||
|
||||
|
||||
|
@ -117,7 +117,9 @@ public:
|
||||
typename C::iterator it = _rResult.begin();
|
||||
typename C::iterator end = _rResult.end();
|
||||
for (int row = 0; it !=end; ++it, ++row)
|
||||
_nulls.push_back(pExt->isNull(col, row));
|
||||
{
|
||||
_nulls.push_back(isValueNull(*it, pExt->isNull(col, row)));
|
||||
}
|
||||
|
||||
return _rResult.size();
|
||||
}
|
||||
|
@ -115,7 +115,8 @@ public:
|
||||
_extracted = true;
|
||||
AbstractExtractor* pExt = getExtractor();
|
||||
TypeHandler<T>::extract(pos, _rResult, _default, pExt);
|
||||
_null = pExt->isNull(pos);
|
||||
_null = isValueNull<T>(_rResult, pExt->isNull(pos));
|
||||
|
||||
return 1u;
|
||||
}
|
||||
|
||||
@ -199,7 +200,7 @@ public:
|
||||
AbstractExtractor* pExt = getExtractor();
|
||||
_rResult.push_back(_default);
|
||||
TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
|
||||
_nulls.push_back(pExt->isNull(pos));
|
||||
_nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos)));
|
||||
return 1u;
|
||||
}
|
||||
|
||||
@ -359,7 +360,7 @@ public:
|
||||
AbstractExtractor* pExt = getExtractor();
|
||||
_rResult.push_back(_default);
|
||||
TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
|
||||
_nulls.push_back(pExt->isNull(pos));
|
||||
_nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos)));
|
||||
return 1u;
|
||||
}
|
||||
|
||||
@ -438,7 +439,7 @@ public:
|
||||
AbstractExtractor* pExt = getExtractor();
|
||||
_rResult.push_back(_default);
|
||||
TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
|
||||
_nulls.push_back(pExt->isNull(pos));
|
||||
_nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos)));
|
||||
return 1u;
|
||||
}
|
||||
|
||||
|
@ -42,9 +42,6 @@
|
||||
#include "Poco/Data/AbstractBinder.h"
|
||||
#include <iostream>
|
||||
|
||||
//using namespace Poco::Data::Keywords;
|
||||
//using Poco::Data::NullData;
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
@ -124,7 +121,7 @@ public:
|
||||
}
|
||||
|
||||
bool operator < (const Nullable<T>& other) const
|
||||
/// Compares two Nullable
|
||||
/// Compares two Nullable objects
|
||||
{
|
||||
if (_isNull < other._isNull)
|
||||
return true;
|
||||
@ -132,13 +129,13 @@ public:
|
||||
}
|
||||
|
||||
operator T& ()
|
||||
/// Get referens to value
|
||||
/// Get reference to the value
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
operator const T& () const
|
||||
/// Get const referens to value
|
||||
/// Get const reference to the value
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
@ -47,7 +47,9 @@ AbstractExtraction::AbstractExtraction(Poco::UInt32 limit,
|
||||
_pExtractor(0),
|
||||
_limit(limit),
|
||||
_position(position),
|
||||
_bulk(bulk)
|
||||
_bulk(bulk),
|
||||
_emptyStringIsNull(false),
|
||||
_forceEmptyString(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -57,4 +59,16 @@ AbstractExtraction::~AbstractExtraction()
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
bool AbstractExtraction::isValueNull(const std::string& str, bool deflt)
|
||||
{
|
||||
if (getForceEmptyString()) return false;
|
||||
|
||||
if (getEmptyStringIsNull() && str.empty())
|
||||
return true;
|
||||
|
||||
return deflt;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
@ -59,7 +59,6 @@ MetaColumn::MetaColumn(std::size_t position,
|
||||
_type(type),
|
||||
_nullable(nullable)
|
||||
{
|
||||
poco_assert(position >= 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -93,6 +93,8 @@ RecordSet::~RecordSet()
|
||||
|
||||
DynamicAny RecordSet::value(std::size_t col, std::size_t row) const
|
||||
{
|
||||
if (isNull(col, row)) return DynamicAny();
|
||||
|
||||
switch (columnType(col))
|
||||
{
|
||||
case MetaColumn::FDT_BOOL: return value<bool>(col, row);
|
||||
@ -119,6 +121,8 @@ DynamicAny RecordSet::value(std::size_t col, std::size_t row) const
|
||||
|
||||
DynamicAny RecordSet::value(const std::string& name, std::size_t row) const
|
||||
{
|
||||
if (isNull(metaColumn(name).position(), row)) return DynamicAny();
|
||||
|
||||
switch (columnType(name))
|
||||
{
|
||||
case MetaColumn::FDT_BOOL: return value<bool>(name, row);
|
||||
|
@ -364,6 +364,12 @@ void StatementImpl::addExtract(AbstractExtraction* pExtraction)
|
||||
if (pos >= _extractors.size())
|
||||
_extractors.resize(pos + 1);
|
||||
|
||||
pExtraction->setEmptyStringIsNull(
|
||||
_rSession.getFeature("emptyStringIsNull"));
|
||||
|
||||
pExtraction->setForceEmptyString(
|
||||
_rSession.getFeature("forceEmptyString"));
|
||||
|
||||
_extractors[pos].push_back(pExtraction);
|
||||
}
|
||||
|
||||
|
@ -325,6 +325,7 @@ public:
|
||||
bool operator == (const T& other) const
|
||||
/// Equality operator
|
||||
{
|
||||
if (isEmpty()) return false;
|
||||
return convert<T>() == other;
|
||||
}
|
||||
|
||||
@ -338,6 +339,7 @@ public:
|
||||
bool operator != (const T& other) const
|
||||
/// Inequality operator
|
||||
{
|
||||
if (isEmpty()) return true;
|
||||
return convert<T>() != other;
|
||||
}
|
||||
|
||||
@ -351,6 +353,7 @@ public:
|
||||
bool operator < (const T& other) const
|
||||
/// Less than operator
|
||||
{
|
||||
if (isEmpty()) return false;
|
||||
return convert<T>() < other;
|
||||
}
|
||||
|
||||
@ -358,6 +361,7 @@ public:
|
||||
bool operator <= (const T& other) const
|
||||
/// Less than or equal operator
|
||||
{
|
||||
if (isEmpty()) return false;
|
||||
return convert<T>() <= other;
|
||||
}
|
||||
|
||||
@ -365,6 +369,7 @@ public:
|
||||
bool operator > (const T& other) const
|
||||
/// Greater than operator
|
||||
{
|
||||
if (isEmpty()) return false;
|
||||
return convert<T>() > other;
|
||||
}
|
||||
|
||||
@ -372,6 +377,7 @@ public:
|
||||
bool operator >= (const T& other) const
|
||||
/// Greater than or equal operator
|
||||
{
|
||||
if (isEmpty()) return false;
|
||||
return convert<T>() >= other;
|
||||
}
|
||||
|
||||
@ -537,39 +543,6 @@ inline DynamicAny& DynamicAny::operator += (const char*other)
|
||||
}
|
||||
|
||||
|
||||
inline bool DynamicAny::operator == (const DynamicAny& other) const
|
||||
{
|
||||
if (isEmpty() || other.isEmpty()) return false;
|
||||
return convert<std::string>() == other.convert<std::string>();
|
||||
}
|
||||
|
||||
|
||||
inline bool DynamicAny::operator == (const char* other) const
|
||||
{
|
||||
return convert<std::string>() == other;
|
||||
}
|
||||
|
||||
|
||||
inline bool DynamicAny::operator != (const DynamicAny& other) const
|
||||
{
|
||||
if (isEmpty() || other.isEmpty()) return false;
|
||||
return convert<std::string>() != other.convert<std::string>();
|
||||
}
|
||||
|
||||
|
||||
inline bool DynamicAny::operator != (const char* other) const
|
||||
{
|
||||
return convert<std::string>() != other;
|
||||
}
|
||||
|
||||
|
||||
inline void DynamicAny::empty()
|
||||
{
|
||||
delete _pHolder;
|
||||
_pHolder = 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool DynamicAny::isEmpty() const
|
||||
{
|
||||
return 0 == _pHolder;
|
||||
@ -683,6 +656,7 @@ inline char operator /= (char& other, const DynamicAny& da)
|
||||
inline const bool operator == (const char& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with char
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<char>();
|
||||
}
|
||||
|
||||
@ -690,6 +664,7 @@ inline const bool operator == (const char& other, const DynamicAny& da)
|
||||
inline const bool operator != (const char& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with char
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<char>();
|
||||
}
|
||||
|
||||
@ -697,6 +672,7 @@ inline const bool operator != (const char& other, const DynamicAny& da)
|
||||
inline const bool operator < (const char& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with char
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<char>();
|
||||
}
|
||||
|
||||
@ -704,6 +680,7 @@ inline const bool operator < (const char& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const char& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with char
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<char>();
|
||||
}
|
||||
|
||||
@ -711,6 +688,7 @@ inline const bool operator <= (const char& other, const DynamicAny& da)
|
||||
inline const bool operator > (const char& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with char
|
||||
{
|
||||
if (da.isEmpty())return false;
|
||||
return other > da.convert<char>();
|
||||
}
|
||||
|
||||
@ -718,6 +696,7 @@ inline const bool operator > (const char& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const char& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with char
|
||||
{
|
||||
if (da.isEmpty())return false;
|
||||
return other >= da.convert<char>();
|
||||
}
|
||||
|
||||
@ -781,6 +760,7 @@ inline Poco::Int8 operator /= (Poco::Int8& other, const DynamicAny& da)
|
||||
inline const bool operator == (const Poco::Int8& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with Poco::Int8
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<Poco::Int8>();
|
||||
}
|
||||
|
||||
@ -788,6 +768,7 @@ inline const bool operator == (const Poco::Int8& other, const DynamicAny& da)
|
||||
inline const bool operator != (const Poco::Int8& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with Poco::Int8
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<Poco::Int8>();
|
||||
}
|
||||
|
||||
@ -795,6 +776,7 @@ inline const bool operator != (const Poco::Int8& other, const DynamicAny& da)
|
||||
inline const bool operator < (const Poco::Int8& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with Poco::Int8
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<Poco::Int8>();
|
||||
}
|
||||
|
||||
@ -802,6 +784,7 @@ inline const bool operator < (const Poco::Int8& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const Poco::Int8& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with Poco::Int8
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<Poco::Int8>();
|
||||
}
|
||||
|
||||
@ -809,6 +792,7 @@ inline const bool operator <= (const Poco::Int8& other, const DynamicAny& da)
|
||||
inline const bool operator > (const Poco::Int8& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with Poco::Int8
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other > da.convert<Poco::Int8>();
|
||||
}
|
||||
|
||||
@ -816,6 +800,7 @@ inline const bool operator > (const Poco::Int8& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const Poco::Int8& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with Poco::Int8
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other >= da.convert<Poco::Int8>();
|
||||
}
|
||||
|
||||
@ -879,6 +864,7 @@ inline Poco::UInt8 operator /= (Poco::UInt8& other, const DynamicAny& da)
|
||||
inline const bool operator == (const Poco::UInt8& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with Poco::UInt8
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<Poco::UInt8>();
|
||||
}
|
||||
|
||||
@ -886,6 +872,7 @@ inline const bool operator == (const Poco::UInt8& other, const DynamicAny& da)
|
||||
inline const bool operator != (const Poco::UInt8& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with Poco::UInt8
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<Poco::UInt8>();
|
||||
}
|
||||
|
||||
@ -893,6 +880,7 @@ inline const bool operator != (const Poco::UInt8& other, const DynamicAny& da)
|
||||
inline const bool operator < (const Poco::UInt8& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with Poco::UInt8
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<Poco::UInt8>();
|
||||
}
|
||||
|
||||
@ -900,6 +888,7 @@ inline const bool operator < (const Poco::UInt8& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const Poco::UInt8& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with Poco::UInt8
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<Poco::UInt8>();
|
||||
}
|
||||
|
||||
@ -907,6 +896,7 @@ inline const bool operator <= (const Poco::UInt8& other, const DynamicAny& da)
|
||||
inline const bool operator > (const Poco::UInt8& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with Poco::UInt8
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other > da.convert<Poco::UInt8>();
|
||||
}
|
||||
|
||||
@ -914,6 +904,7 @@ inline const bool operator > (const Poco::UInt8& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const Poco::UInt8& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with Poco::UInt8
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other >= da.convert<Poco::UInt8>();
|
||||
}
|
||||
|
||||
@ -977,6 +968,7 @@ inline Poco::Int16 operator /= (Poco::Int16& other, const DynamicAny& da)
|
||||
inline const bool operator == (const Poco::Int16& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with Poco::Int16
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<Poco::Int16>();
|
||||
}
|
||||
|
||||
@ -984,6 +976,7 @@ inline const bool operator == (const Poco::Int16& other, const DynamicAny& da)
|
||||
inline const bool operator != (const Poco::Int16& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with Poco::Int16
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<Poco::Int16>();
|
||||
}
|
||||
|
||||
@ -991,6 +984,7 @@ inline const bool operator != (const Poco::Int16& other, const DynamicAny& da)
|
||||
inline const bool operator < (const Poco::Int16& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with Poco::Int16
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<Poco::Int16>();
|
||||
}
|
||||
|
||||
@ -998,6 +992,7 @@ inline const bool operator < (const Poco::Int16& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const Poco::Int16& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with Poco::Int16
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<Poco::Int16>();
|
||||
}
|
||||
|
||||
@ -1005,6 +1000,7 @@ inline const bool operator <= (const Poco::Int16& other, const DynamicAny& da)
|
||||
inline const bool operator > (const Poco::Int16& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with Poco::Int16
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other > da.convert<Poco::Int16>();
|
||||
}
|
||||
|
||||
@ -1012,6 +1008,7 @@ inline const bool operator > (const Poco::Int16& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const Poco::Int16& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with Poco::Int16
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other >= da.convert<Poco::Int16>();
|
||||
}
|
||||
|
||||
@ -1075,6 +1072,7 @@ inline Poco::UInt16 operator /= (Poco::UInt16& other, const DynamicAny& da)
|
||||
inline const bool operator == (const Poco::UInt16& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with Poco::UInt16
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<Poco::UInt16>();
|
||||
}
|
||||
|
||||
@ -1082,6 +1080,7 @@ inline const bool operator == (const Poco::UInt16& other, const DynamicAny& da)
|
||||
inline const bool operator != (const Poco::UInt16& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with Poco::UInt16
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<Poco::UInt16>();
|
||||
}
|
||||
|
||||
@ -1089,6 +1088,7 @@ inline const bool operator != (const Poco::UInt16& other, const DynamicAny& da)
|
||||
inline const bool operator < (const Poco::UInt16& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with Poco::UInt16
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<Poco::UInt16>();
|
||||
}
|
||||
|
||||
@ -1096,6 +1096,7 @@ inline const bool operator < (const Poco::UInt16& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const Poco::UInt16& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with Poco::UInt16
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<Poco::UInt16>();
|
||||
}
|
||||
|
||||
@ -1103,6 +1104,7 @@ inline const bool operator <= (const Poco::UInt16& other, const DynamicAny& da)
|
||||
inline const bool operator > (const Poco::UInt16& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with Poco::UInt16
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other > da.convert<Poco::UInt16>();
|
||||
}
|
||||
|
||||
@ -1110,6 +1112,7 @@ inline const bool operator > (const Poco::UInt16& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const Poco::UInt16& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with Poco::UInt16
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other >= da.convert<Poco::UInt16>();
|
||||
}
|
||||
|
||||
@ -1173,6 +1176,7 @@ inline Poco::Int32 operator /= (Poco::Int32& other, const DynamicAny& da)
|
||||
inline const bool operator == (const Poco::Int32& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with Poco::Int32
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<Poco::Int32>();
|
||||
}
|
||||
|
||||
@ -1180,6 +1184,7 @@ inline const bool operator == (const Poco::Int32& other, const DynamicAny& da)
|
||||
inline const bool operator != (const Poco::Int32& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with Poco::Int32
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<Poco::Int32>();
|
||||
}
|
||||
|
||||
@ -1187,6 +1192,7 @@ inline const bool operator != (const Poco::Int32& other, const DynamicAny& da)
|
||||
inline const bool operator < (const Poco::Int32& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with Poco::Int32
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<Poco::Int32>();
|
||||
}
|
||||
|
||||
@ -1194,6 +1200,7 @@ inline const bool operator < (const Poco::Int32& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const Poco::Int32& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with Poco::Int32
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<Poco::Int32>();
|
||||
}
|
||||
|
||||
@ -1201,6 +1208,7 @@ inline const bool operator <= (const Poco::Int32& other, const DynamicAny& da)
|
||||
inline const bool operator > (const Poco::Int32& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with Poco::Int32
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other > da.convert<Poco::Int32>();
|
||||
}
|
||||
|
||||
@ -1208,6 +1216,7 @@ inline const bool operator > (const Poco::Int32& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const Poco::Int32& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with Poco::Int32
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other >= da.convert<Poco::Int32>();
|
||||
}
|
||||
|
||||
@ -1271,6 +1280,7 @@ inline Poco::UInt32 operator /= (Poco::UInt32& other, const DynamicAny& da)
|
||||
inline const bool operator == (const Poco::UInt32& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with Poco::UInt32
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<Poco::UInt32>();
|
||||
}
|
||||
|
||||
@ -1278,6 +1288,7 @@ inline const bool operator == (const Poco::UInt32& other, const DynamicAny& da)
|
||||
inline const bool operator != (const Poco::UInt32& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with Poco::UInt32
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<Poco::UInt32>();
|
||||
}
|
||||
|
||||
@ -1285,6 +1296,7 @@ inline const bool operator != (const Poco::UInt32& other, const DynamicAny& da)
|
||||
inline const bool operator < (const Poco::UInt32& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with Poco::UInt32
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<Poco::UInt32>();
|
||||
}
|
||||
|
||||
@ -1292,6 +1304,7 @@ inline const bool operator < (const Poco::UInt32& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const Poco::UInt32& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with Poco::UInt32
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<Poco::UInt32>();
|
||||
}
|
||||
|
||||
@ -1299,6 +1312,7 @@ inline const bool operator <= (const Poco::UInt32& other, const DynamicAny& da)
|
||||
inline const bool operator > (const Poco::UInt32& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with Poco::UInt32
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other > da.convert<Poco::UInt32>();
|
||||
}
|
||||
|
||||
@ -1306,6 +1320,7 @@ inline const bool operator > (const Poco::UInt32& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const Poco::UInt32& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with Poco::UInt32
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other >= da.convert<Poco::UInt32>();
|
||||
}
|
||||
|
||||
@ -1369,6 +1384,7 @@ inline Poco::Int64 operator /= (Poco::Int64& other, const DynamicAny& da)
|
||||
inline const bool operator == (const Poco::Int64& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with Poco::Int64
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<Poco::Int64>();
|
||||
}
|
||||
|
||||
@ -1376,6 +1392,7 @@ inline const bool operator == (const Poco::Int64& other, const DynamicAny& da)
|
||||
inline const bool operator != (const Poco::Int64& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with Poco::Int64
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<Poco::Int64>();
|
||||
}
|
||||
|
||||
@ -1383,6 +1400,7 @@ inline const bool operator != (const Poco::Int64& other, const DynamicAny& da)
|
||||
inline const bool operator < (const Poco::Int64& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with Poco::Int64
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<Poco::Int64>();
|
||||
}
|
||||
|
||||
@ -1390,6 +1408,7 @@ inline const bool operator < (const Poco::Int64& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const Poco::Int64& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with Poco::Int64
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<Poco::Int64>();
|
||||
}
|
||||
|
||||
@ -1397,6 +1416,7 @@ inline const bool operator <= (const Poco::Int64& other, const DynamicAny& da)
|
||||
inline const bool operator > (const Poco::Int64& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with Poco::Int64
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other > da.convert<Poco::Int64>();
|
||||
}
|
||||
|
||||
@ -1404,6 +1424,7 @@ inline const bool operator > (const Poco::Int64& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const Poco::Int64& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with Poco::Int64
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other >= da.convert<Poco::Int64>();
|
||||
}
|
||||
|
||||
@ -1467,6 +1488,7 @@ inline Poco::UInt64 operator /= (Poco::UInt64& other, const DynamicAny& da)
|
||||
inline const bool operator == (const Poco::UInt64& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with Poco::UInt64
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<Poco::UInt64>();
|
||||
}
|
||||
|
||||
@ -1474,6 +1496,7 @@ inline const bool operator == (const Poco::UInt64& other, const DynamicAny& da)
|
||||
inline const bool operator != (const Poco::UInt64& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with Poco::UInt64
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<Poco::UInt64>();
|
||||
}
|
||||
|
||||
@ -1481,6 +1504,7 @@ inline const bool operator != (const Poco::UInt64& other, const DynamicAny& da)
|
||||
inline const bool operator < (const Poco::UInt64& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with Poco::UInt64
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<Poco::UInt64>();
|
||||
}
|
||||
|
||||
@ -1488,6 +1512,7 @@ inline const bool operator < (const Poco::UInt64& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const Poco::UInt64& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with Poco::UInt64
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<Poco::UInt64>();
|
||||
}
|
||||
|
||||
@ -1495,6 +1520,7 @@ inline const bool operator <= (const Poco::UInt64& other, const DynamicAny& da)
|
||||
inline const bool operator > (const Poco::UInt64& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with Poco::UInt64
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other > da.convert<Poco::UInt64>();
|
||||
}
|
||||
|
||||
@ -1502,6 +1528,7 @@ inline const bool operator > (const Poco::UInt64& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const Poco::UInt64& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with Poco::UInt64
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other >= da.convert<Poco::UInt64>();
|
||||
}
|
||||
|
||||
@ -1565,6 +1592,7 @@ inline float operator /= (float& other, const DynamicAny& da)
|
||||
inline const bool operator == (const float& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with float
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<float>();
|
||||
}
|
||||
|
||||
@ -1572,6 +1600,7 @@ inline const bool operator == (const float& other, const DynamicAny& da)
|
||||
inline const bool operator != (const float& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with float
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<float>();
|
||||
}
|
||||
|
||||
@ -1579,6 +1608,7 @@ inline const bool operator != (const float& other, const DynamicAny& da)
|
||||
inline const bool operator < (const float& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with float
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<float>();
|
||||
}
|
||||
|
||||
@ -1586,6 +1616,7 @@ inline const bool operator < (const float& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const float& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with float
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<float>();
|
||||
}
|
||||
|
||||
@ -1593,6 +1624,7 @@ inline const bool operator <= (const float& other, const DynamicAny& da)
|
||||
inline const bool operator > (const float& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with float
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other > da.convert<float>();
|
||||
}
|
||||
|
||||
@ -1600,6 +1632,7 @@ inline const bool operator > (const float& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const float& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with float
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other >= da.convert<float>();
|
||||
}
|
||||
|
||||
@ -1663,6 +1696,7 @@ inline double operator /= (double& other, const DynamicAny& da)
|
||||
inline const bool operator == (const double& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with double
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<double>();
|
||||
}
|
||||
|
||||
@ -1670,6 +1704,7 @@ inline const bool operator == (const double& other, const DynamicAny& da)
|
||||
inline const bool operator != (const double& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with double
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<double>();
|
||||
}
|
||||
|
||||
@ -1677,6 +1712,7 @@ inline const bool operator != (const double& other, const DynamicAny& da)
|
||||
inline const bool operator < (const double& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with double
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<double>();
|
||||
}
|
||||
|
||||
@ -1684,6 +1720,7 @@ inline const bool operator < (const double& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const double& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with double
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<double>();
|
||||
}
|
||||
|
||||
@ -1691,6 +1728,7 @@ inline const bool operator <= (const double& other, const DynamicAny& da)
|
||||
inline const bool operator > (const double& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with double
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other > da.convert<double>();
|
||||
}
|
||||
|
||||
@ -1698,6 +1736,7 @@ inline const bool operator > (const double& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const double& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with double
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other >= da.convert<double>();
|
||||
}
|
||||
|
||||
@ -1705,6 +1744,7 @@ inline const bool operator >= (const double& other, const DynamicAny& da)
|
||||
inline const bool operator == (const bool& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with bool
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<bool>();
|
||||
}
|
||||
|
||||
@ -1712,6 +1752,7 @@ inline const bool operator == (const bool& other, const DynamicAny& da)
|
||||
inline const bool operator != (const bool& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with bool
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<bool>();
|
||||
}
|
||||
|
||||
@ -1719,6 +1760,7 @@ inline const bool operator != (const bool& other, const DynamicAny& da)
|
||||
inline const bool operator == (const std::string& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with std::string
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<std::string>();
|
||||
}
|
||||
|
||||
@ -1726,6 +1768,7 @@ inline const bool operator == (const std::string& other, const DynamicAny& da)
|
||||
inline const bool operator != (const std::string& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with std::string
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<std::string>();
|
||||
}
|
||||
|
||||
@ -1733,6 +1776,7 @@ inline const bool operator != (const std::string& other, const DynamicAny& da)
|
||||
inline const bool operator == (const char* other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with const char*
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return da.convert<std::string>() == other;
|
||||
}
|
||||
|
||||
@ -1740,6 +1784,7 @@ inline const bool operator == (const char* other, const DynamicAny& da)
|
||||
inline const bool operator != (const char* other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with const char*
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return da.convert<std::string>() != other;
|
||||
}
|
||||
|
||||
@ -1806,6 +1851,7 @@ inline long operator /= (long& other, const DynamicAny& da)
|
||||
inline const bool operator == (const long& other, const DynamicAny& da)
|
||||
/// Equality operator for comparing DynamicAny with long
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other == da.convert<long>();
|
||||
}
|
||||
|
||||
@ -1813,6 +1859,7 @@ inline const bool operator == (const long& other, const DynamicAny& da)
|
||||
inline const bool operator != (const long& other, const DynamicAny& da)
|
||||
/// Inequality operator for comparing DynamicAny with long
|
||||
{
|
||||
if (da.isEmpty()) return true;
|
||||
return other != da.convert<long>();
|
||||
}
|
||||
|
||||
@ -1820,6 +1867,7 @@ inline const bool operator != (const long& other, const DynamicAny& da)
|
||||
inline const bool operator < (const long& other, const DynamicAny& da)
|
||||
/// Less than operator for comparing DynamicAny with long
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other < da.convert<long>();
|
||||
}
|
||||
|
||||
@ -1827,6 +1875,7 @@ inline const bool operator < (const long& other, const DynamicAny& da)
|
||||
inline const bool operator <= (const long& other, const DynamicAny& da)
|
||||
/// Less than or equal operator for comparing DynamicAny with long
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other <= da.convert<long>();
|
||||
}
|
||||
|
||||
@ -1834,6 +1883,7 @@ inline const bool operator <= (const long& other, const DynamicAny& da)
|
||||
inline const bool operator > (const long& other, const DynamicAny& da)
|
||||
/// Greater than operator for comparing DynamicAny with long
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other > da.convert<long>();
|
||||
}
|
||||
|
||||
@ -1841,6 +1891,7 @@ inline const bool operator > (const long& other, const DynamicAny& da)
|
||||
inline const bool operator >= (const long& other, const DynamicAny& da)
|
||||
/// Greater than or equal operator for comparing DynamicAny with long
|
||||
{
|
||||
if (da.isEmpty()) return false;
|
||||
return other >= da.convert<long>();
|
||||
}
|
||||
|
||||
|
@ -245,6 +245,43 @@ DynamicAny DynamicAny::operator -- (int)
|
||||
}
|
||||
|
||||
|
||||
bool DynamicAny::operator == (const DynamicAny& other) const
|
||||
{
|
||||
if (isEmpty() || other.isEmpty()) return false;
|
||||
return convert<std::string>() == other.convert<std::string>();
|
||||
}
|
||||
|
||||
|
||||
bool DynamicAny::operator == (const char* other) const
|
||||
{
|
||||
if (isEmpty()) return false;
|
||||
return convert<std::string>() == other;
|
||||
}
|
||||
|
||||
|
||||
bool DynamicAny::operator != (const DynamicAny& other) const
|
||||
{
|
||||
if (isEmpty() && other.isEmpty()) return false;
|
||||
else if (isEmpty() || other.isEmpty()) return true;
|
||||
|
||||
return convert<std::string>() != other.convert<std::string>();
|
||||
}
|
||||
|
||||
|
||||
bool DynamicAny::operator != (const char* other) const
|
||||
{
|
||||
if (isEmpty()) return true;
|
||||
return convert<std::string>() != other;
|
||||
}
|
||||
|
||||
|
||||
void DynamicAny::empty()
|
||||
{
|
||||
delete _pHolder;
|
||||
_pHolder = 0;
|
||||
}
|
||||
|
||||
|
||||
DynamicAny& DynamicAny::operator [] (const std::string& name)
|
||||
{
|
||||
return holderImpl<DynamicStruct, InvalidAccessException>("Not an array.")->operator[](name);
|
||||
|
@ -2302,6 +2302,29 @@ void DynamicAnyTest::testEmpty()
|
||||
assert (!(da == da));
|
||||
assert (!(da != da));
|
||||
|
||||
assert (da != "");
|
||||
assert ("" != da);
|
||||
assert (!(da == ""));
|
||||
assert (!("" == da));
|
||||
|
||||
|
||||
testEmptyComparisons<unsigned char>();
|
||||
testEmptyComparisons<char>();
|
||||
testEmptyComparisons<Poco::UInt8>();
|
||||
testEmptyComparisons<Poco::Int8>();
|
||||
testEmptyComparisons<Poco::UInt16>();
|
||||
testEmptyComparisons<Poco::Int16>();
|
||||
testEmptyComparisons<Poco::UInt32>();
|
||||
testEmptyComparisons<Poco::Int32>();
|
||||
testEmptyComparisons<Poco::UInt64>();
|
||||
testEmptyComparisons<Poco::Int64>();
|
||||
#ifdef POCO_LONG_IS_64_BIT
|
||||
testEmptyComparisons<unsigned long>();
|
||||
testEmptyComparisons<long>();
|
||||
#endif
|
||||
testEmptyComparisons<float>();
|
||||
testEmptyComparisons<double>();
|
||||
|
||||
try
|
||||
{
|
||||
int i = da;
|
||||
|
@ -159,6 +159,26 @@ private:
|
||||
try { TS i; i = da.convert<TS>(); fail("must fail"); }
|
||||
catch (Poco::RangeException&) {}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void testEmptyComparisons()
|
||||
{
|
||||
DynamicAny da;
|
||||
T val = 0;
|
||||
|
||||
assert (da != val);
|
||||
assert (val != da);
|
||||
assert (!(val == da));
|
||||
assert (!(da == val));
|
||||
assert (!(da < val));
|
||||
assert (!(val < da));
|
||||
assert (!(da > val));
|
||||
assert (!(val > da));
|
||||
assert (!(da <= val));
|
||||
assert (!(val <= da));
|
||||
assert (!(da >= val));
|
||||
assert (!(val >= da));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user