JSON Formatter modifications

This commit is contained in:
Alex Fabijanic 2015-02-12 20:49:35 -06:00
parent 16260784da
commit 07a2529d9d
17 changed files with 599 additions and 157 deletions

View File

@ -303,7 +303,7 @@
<ClInclude Include="include\Poco\Data\DynamicDateTime.h" />
<ClInclude Include="include\Poco\Data\DynamicLOB.h" />
<ClInclude Include="include\Poco\Data\Extraction.h" />
<ClInclude Include="include\Poco\Data\JSONFormatter.h" />
<ClInclude Include="include\Poco\Data\JSONRowFormatter.h" />
<ClInclude Include="include\Poco\Data\Limit.h" />
<ClInclude Include="include\Poco\Data\LOB.h" />
<ClInclude Include="include\Poco\Data\LOBStream.h" />
@ -345,7 +345,7 @@
<ClCompile Include="src\DataException.cpp" />
<ClCompile Include="src\Date.cpp" />
<ClCompile Include="src\DynamicLOB.cpp" />
<ClCompile Include="src\JSONFormatter.cpp" />
<ClCompile Include="src\JSONRowFormatter.cpp" />
<ClCompile Include="src\Limit.cpp" />
<ClCompile Include="src\MetaColumn.cpp" />
<ClCompile Include="src\PooledSessionHolder.cpp" />

View File

@ -177,7 +177,7 @@
<ClInclude Include="include\Poco\Data\SQLChannel.h">
<Filter>Logging\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\Data\JSONFormatter.h">
<ClInclude Include="include\Poco\Data\JSONRowFormatter.h">
<Filter>DataCore\Header Files</Filter>
</ClInclude>
</ItemGroup>
@ -287,7 +287,7 @@
<ClCompile Include="src\SQLChannel.cpp">
<Filter>Logging\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\JSONFormatter.cpp">
<ClCompile Include="src\JSONRowFormatter.cpp">
<Filter>DataCore\Source Files</Filter>
</ClCompile>
</ItemGroup>

View File

@ -18,6 +18,7 @@
#include "Poco/Data/LOB.h"
#include "Poco/Data/Statement.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/Data/JSONRowFormatter.h"
#include "Poco/Data/SQLChannel.h"
#include "Poco/Data/SessionFactory.h"
#include "Poco/Data/SQLite/Connector.h"
@ -49,6 +50,7 @@ using namespace Poco::Data::Keywords;
using Poco::Data::Session;
using Poco::Data::Statement;
using Poco::Data::RecordSet;
using Poco::Data::JSONRowFormatter;
using Poco::Data::Column;
using Poco::Data::Row;
using Poco::Data::SQLChannel;
@ -3356,6 +3358,85 @@ void SQLiteTest::testFTS3()
}
void SQLiteTest::testJSONRowFormatter()
{
Session tmp(Poco::Data::SQLite::Connector::KEY, "dummy.db");
assert(tmp.isConnected());
std::string lastName("Simpson");
std::string firstName("Bart");
std::string address("Springfield");
int age = 12;
tmp << "DROP TABLE IF EXISTS Simpsons", now;
tmp << "CREATE TABLE IF NOT EXISTS Simpsons (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
checkJSON("SELECT * FROM Simpsons", "");
tmp << "INSERT INTO Simpsons VALUES(?, ?, ?, ?)", use(lastName), use(firstName), use(address), use(age), now;
checkJSON("SELECT * FROM Simpsons",
"{"
"\"names\":[\"LastName\",\"FirstName\",\"Address\",\"Age\"],"
"\"values\":[[\"Simpson\",\"Bart\",\"Springfield\",12]]"
"}");
lastName = "Simpson";
firstName ="Lisa";
address ="Springfield";
age = 10;
tmp << "INSERT INTO Simpsons VALUES(?, ?, ?, ?)", use(lastName), use(firstName), use(address), use(age), now;
checkJSON("SELECT * FROM Simpsons",
"{"
"\"names\":[\"LastName\",\"FirstName\",\"Address\",\"Age\"],"
"\"values\":[[\"Simpson\",\"Bart\",\"Springfield\",12],"
"[\"Simpson\",\"Lisa\",\"Springfield\",10]]"
"}");
checkJSON("SELECT * FROM Simpsons",
"{"
"[[\"Simpson\",\"Bart\",\"Springfield\",12],"
"[\"Simpson\",\"Lisa\",\"Springfield\",10]]"
"}", JSONRowFormatter::JSON_FMT_MODE_SMALL);
checkJSON("SELECT * FROM Simpsons",
"{\"count\":2,"
"[[\"Simpson\",\"Bart\",\"Springfield\",12],"
"[\"Simpson\",\"Lisa\",\"Springfield\",10]]"
"}", JSONRowFormatter::JSON_FMT_MODE_ROW_COUNT);
checkJSON("SELECT * FROM Simpsons",
"{"
"\"names\":[\"LastName\",\"FirstName\",\"Address\",\"Age\"],"
"\"values\":[[\"Simpson\",\"Bart\",\"Springfield\",12],"
"[\"Simpson\",\"Lisa\",\"Springfield\",10]]"
"}", JSONRowFormatter::JSON_FMT_MODE_COLUMN_NAMES);
checkJSON("SELECT * FROM Simpsons",
"{\"count\":2,"
"[{\"LastName\":\"Simpson\",\"FirstName\":\"Bart\",\"Address\":\"Springfield\",\"Age\":12},"
"{\"LastName\":\"Simpson\",\"FirstName\":\"Lisa\",\"Address\":\"Springfield\",\"Age\":10}]"
"}", JSONRowFormatter::JSON_FMT_MODE_FULL);
}
void SQLiteTest::checkJSON(const std::string& sql, const std::string& json, int mode)
{
Session tmp(Poco::Data::SQLite::Connector::KEY, "dummy.db");
JSONRowFormatter jf;
if (mode > 0)
jf.setJSONMode(mode);
Statement stmt = (tmp << sql, format(jf), now);
RecordSet rs(stmt);
std::ostringstream ostr;
ostr << rs;
assert(ostr.str() == json);
}
void SQLiteTest::setUp()
{
}
@ -3456,6 +3537,7 @@ CppUnit::Test* SQLiteTest::suite()
CppUnit_addTest(pSuite, SQLiteTest, testTransaction);
CppUnit_addTest(pSuite, SQLiteTest, testTransactor);
CppUnit_addTest(pSuite, SQLiteTest, testFTS3);
CppUnit_addTest(pSuite, SQLiteTest, testJSONRowFormatter);
return pSuite;
}

View File

@ -135,6 +135,8 @@ public:
void testFTS3();
void testJSONRowFormatter();
void setUp();
void tearDown();
@ -152,6 +154,7 @@ public:
private:
void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti);
void checkJSON(const std::string& sql, const std::string& json, int mode = 0);
static int _insertCounter;
static int _updateCounter;

View File

@ -215,6 +215,21 @@ public:
return _val;
}
bool isDate() const
{
return true;
}
bool isTime() const
{
return false;
}
bool isDateTime() const
{
return false;
}
private:
VarHolderImpl();
Poco::Data::Date _val;

View File

@ -1,62 +0,0 @@
//
// JSONFormatter.h
//
// $Id: //poco/Main/Data/include/Poco/Data/JSONFormatter.h#9 $
//
// Library: Data
// Package: DataCore
// Module: JSONFormatter
//
// Definition of the JSONFormatter class.
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_JSONFormatter_INCLUDED
#define Data_JSONFormatter_INCLUDED
#include "Poco/Data/RowFormatter.h"
namespace Poco {
namespace Data {
class Data_API JSONFormatter: public Poco::Data::RowFormatter
/// Class for JSON formatting of data rows.
{
public:
JSONFormatter();
/// Creates a new JSONFormatter.
~JSONFormatter();
/// Destroy the JSONFormatter.
std::string& formatNames(const NameVecPtr pNames, std::string& formattedNames);
std::string& formatValues(const ValueVec& vals, std::string& formattedValues);
private:
NameVecPtr _pNames;
int _rowCounter;
};
//
// inlines
//
inline std::string& JSONFormatter::formatNames(const NameVecPtr pNames, std::string& formattedNames)
{
// names are used in formatValues
if (pNames && !_pNames) _pNames = pNames;
return formattedNames = "";
}
} } // namespace Poco::Data
#endif // Data_JSONFormatter_INCLUDED

View File

@ -0,0 +1,116 @@
//
// JSONRowFormatter.h
//
// $Id: //poco/Main/Data/include/Poco/Data/JSONRowFormatter.h#9 $
//
// Library: Data
// Package: DataCore
// Module: JSONRowFormatter
//
// Definition of the JSONRowFormatter class.
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_JSONRowFormatter_INCLUDED
#define Data_JSONRowFormatter_INCLUDED
#include "Poco/Data/RowFormatter.h"
namespace Poco {
namespace Data {
class Data_API JSONRowFormatter: public Poco::Data::RowFormatter
/// Class for JSON formatting of data rows.
{
public:
static const int JSON_FMT_MODE_SMALL = 1;
static const int JSON_FMT_MODE_ROW_COUNT = 2;
static const int JSON_FMT_MODE_COLUMN_NAMES = 4;
static const int JSON_FMT_MODE_FULL = 8;
JSONRowFormatter(int mode = (JSON_FMT_MODE_COLUMN_NAMES | JSON_FMT_MODE_SMALL));
/// Creates a new JSONRowFormatter.
~JSONRowFormatter();
/// Destroys the JSONRowFormatter.
std::string& formatNames(const NameVecPtr pNames, std::string& formattedNames);
/// Formats names.
std::string& formatValues(const ValueVec& vals, std::string& formattedValues);
// Formats values.
void setJSONMode(int mode);
/// Sets the mode. Valid mode values are:
/// JSON_FMT_MODE_SMALL
/// JSON_FMT_MODE_ROW_COUNT
/// JSON_FMT_MODE_COLUMN_NAMES
/// JSON_FMT_MODE_FULL
bool printRowCount();
/// Returns true if row count printing is enabled,
/// false otherwise.
bool printColumnNames();
/// Returns true if column names printing is enabled,
/// false otherwise.
bool isSmall();
/// Returns true if compact mode formatting is enabled,
/// false otherwise.
bool isFull();
/// Returns true if full mode formatting is enabled,
/// false otherwise.
private:
void adjustPrefix();
NameVecPtr _pNames;
int _mode;
bool _firstTime;
};
//
// inlines
//
inline bool JSONRowFormatter::printRowCount()
{
return (_mode & JSON_FMT_MODE_ROW_COUNT) != 0;
}
inline bool JSONRowFormatter::printColumnNames()
{
return (_mode & JSON_FMT_MODE_COLUMN_NAMES) != 0;
}
inline bool JSONRowFormatter::isSmall()
{
return (_mode & JSON_FMT_MODE_SMALL) != 0;
}
inline bool JSONRowFormatter::isFull()
{
return (_mode & JSON_FMT_MODE_FULL) != 0;
}
} } // namespace Poco::Data
#endif // Data_JSONRowFormatter_INCLUDED

View File

@ -40,7 +40,7 @@ class Data_API RowFormatter
/// Row formatter can be either passed to the RecordSet at construction time,
/// like in the following example:
///
/// RecordSet rs(session. "SELECT * FROM Table", new MyRowFormater);
/// RecordSet rs(session, "SELECT * FROM Table", new MyRowFormater);
///
/// or it can be supplied to the statement as in the following example:
///
@ -147,6 +147,12 @@ protected:
void setPostfix(const std::string& postfix);
/// Sets the postfix for the formatter
virtual void adjustPrefix();
/// Adjusts prefix after it has been set.
/// No-op here, called by setTotalRowCount and
/// should be implemented by inheriting classes,
/// if needed.
private:
mutable std::string _prefix;
@ -174,6 +180,7 @@ inline int RowFormatter::getTotalRowCount() const
inline void RowFormatter::setTotalRowCount(int count)
{
_totalRowCount = count;
adjustPrefix();
}
@ -213,6 +220,11 @@ inline void RowFormatter::setMode(Mode mode)
}
inline void RowFormatter::adjustPrefix()
{
}
namespace Keywords {

View File

@ -219,6 +219,21 @@ public:
return _val;
}
bool isDate() const
{
return false;
}
bool isTime() const
{
return true;
}
bool isDateTime() const
{
return false;
}
private:
VarHolderImpl();
Poco::Data::Time _val;

View File

@ -1,87 +0,0 @@
//
// JSONFormatter.cpp
//
// $Id: //poco/Main/Data/src/JSONFormatter.cpp#1 $
//
// Library: Data
// Package: DataCore
// Module: JSONFormatter
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/JSONFormatter.h"
#include "Poco/String.h"
#include "Poco/JSONString.h"
#include "Poco/Format.h"
using Poco::trimInPlace;
using Poco::format;
using Poco::toJSON;
namespace Poco {
namespace Data {
JSONFormatter::JSONFormatter() : _rowCounter(0)
{
}
JSONFormatter::~JSONFormatter()
{
}
std::string& JSONFormatter::formatValues(const ValueVec& vals, std::string& formattedValues)
{
std::ostringstream str;
str << "{\"count\":" << getTotalRowCount() << ",\"rows\":[{";
std::string pref = str.str();
if (prefix() != pref) setPrefix(pref);
else
{
str.str("");
str << ",{";
}
if (postfix().empty()) setPostfix("]}");
ValueVec::const_iterator it = vals.begin();
ValueVec::const_iterator end = vals.end();
NameVec::iterator nIt = _pNames->begin();
NameVec::iterator nEnd = _pNames->end();
for (; it != end && nIt != nEnd; ++nIt)
{
if (!it->isEmpty())
{
if (it->isString())
{
std::string val = it->convert<std::string>();
trimInPlace(val);
str << '"' << *nIt << "\":" << toJSON(val);
}
else
str << '"' << *nIt << "\":" << it->convert<std::string>();
}
else
str << '"' << *nIt << "\":null";
if (++it != end) str << ',';
}
str << '}';
++_rowCounter;
return formattedValues = str.str();
}
} }// namespace Poco::Data

View File

@ -0,0 +1,187 @@
//
// JSONRowFormatter.cpp
//
// $Id: //poco/Main/Data/src/JSONRowFormatter.cpp#1 $
//
// Library: Data
// Package: DataCore
// Module: JSONRowFormatter
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/JSONRowFormatter.h"
#include "Poco/String.h"
#include "Poco/JSONString.h"
#include "Poco/Format.h"
using Poco::trimInPlace;
using Poco::format;
using Poco::toJSON;
namespace Poco {
namespace Data {
JSONRowFormatter::JSONRowFormatter(int mode) : RowFormatter("{", "]}"),
_firstTime(true)
{
if (mode == JSON_FMT_MODE_FULL)
{
mode |= JSON_FMT_MODE_ROW_COUNT;
mode |= JSON_FMT_MODE_COLUMN_NAMES;
//setPostfix("]}");
}
setJSONMode(mode);
}
JSONRowFormatter::~JSONRowFormatter()
{
}
void JSONRowFormatter::adjustPrefix()
{
if (printRowCount())
{
std::ostringstream ostr;
ostr << "{\"count\":" << getTotalRowCount() << ",";
if (_mode & JSON_FMT_MODE_FULL)
ostr << '[';
setPrefix(ostr.str());
}
}
void JSONRowFormatter::setJSONMode(int mode)
{
if (mode < JSON_FMT_MODE_SMALL ||
mode > (JSON_FMT_MODE_SMALL | JSON_FMT_MODE_ROW_COUNT | JSON_FMT_MODE_COLUMN_NAMES | JSON_FMT_MODE_FULL))
{
throw Poco::InvalidArgumentException(
Poco::format("JSONRowFormatter mode must be between "
"%d (JSON_FMT_MODE_SMALL) and %d (JSON_FMT_MODE_FULL)",
JSON_FMT_MODE_SMALL,
JSON_FMT_MODE_FULL));
}
_mode = mode;
if (!(_mode & JSON_FMT_MODE_SMALL) && !(_mode & JSON_FMT_MODE_FULL))
_mode |= JSON_FMT_MODE_SMALL;
else if (_mode & JSON_FMT_MODE_FULL)
{
_mode |= JSON_FMT_MODE_ROW_COUNT;
}
adjustPrefix();
}
std::string& JSONRowFormatter::formatValues(const ValueVec& vals, std::string& formattedValues)
{
std::ostringstream str;
if (!_firstTime) str << ',';
if (isSmall())
{
if (_firstTime)
{
if (printColumnNames())
str << ",\"values\":";
str << '[';
}
str << '[';
ValueVec::const_iterator it = vals.begin();
ValueVec::const_iterator end = vals.end();
for (; it != end;)
{
if (!it->isEmpty())
{
if (it->isString() || it->isDate() || it->isTime())
{
std::string val = it->convert<std::string>();
trimInPlace(val);
str << toJSON(val);
}
else
str << it->convert<std::string>();
}
else
str << "null";
if (++it == end) break;
str << ',';
}
str << ']';
}
else if (isFull())
{
str << '{';
ValueVec::const_iterator it = vals.begin();
ValueVec::const_iterator end = vals.end();
NameVec::iterator nIt = _pNames->begin();
NameVec::iterator nEnd = _pNames->end();
for (; it != end && nIt != nEnd; ++nIt)
{
if (!it->isEmpty())
{
if (it->isString() || it->isDate() || it->isTime())
{
std::string val = it->convert<std::string>();
trimInPlace(val);
str << '"' << *nIt << "\":" << toJSON(val);
}
else
str << '"' << *nIt << "\":" << it->convert<std::string>();
}
else
str << '"' << *nIt << "\":null";
if (++it != end) str << ',';
}
str << '}';
}
_firstTime = false;
return formattedValues = str.str();
}
std::string& JSONRowFormatter::formatNames(const NameVecPtr pNames, std::string& formattedNames)
{
if (isFull())
{
// names are used in formatValues
if (pNames && !_pNames) _pNames = pNames;
return formattedNames = "";
}
else if (printColumnNames())
{
std::ostringstream ostr;
ostr << "\"names\":[";
for (NameVec::const_iterator it = pNames->begin(),
end = pNames->end();;)
{
ostr << '"' << *it << '"';
if (++it == end) break;
ostr << ',';
}
ostr << "]";
return formattedNames = ostr.str();
}
return formattedNames = "";
}
} }// namespace Poco::Data

View File

@ -311,6 +311,8 @@ void RecordSet::setRowFormatter(RowFormatter::Ptr pRowFormatter)
std::ostream& RecordSet::copyNames(std::ostream& os) const
{
if (begin() == end()) return os;
std::string names = (*_pBegin)->namesToString();
if (!names.empty()) os << names;
return os;
@ -319,6 +321,8 @@ std::ostream& RecordSet::copyNames(std::ostream& os) const
std::ostream& RecordSet::copyValues(std::ostream& os, std::size_t offset, std::size_t length) const
{
if (begin() == end()) return os;
RowIterator it = *_pBegin + offset;
RowIterator end = (RowIterator::POSITION_END != length) ? it + length : *_pEnd;
std::copy(it, end, std::ostream_iterator<Row>(os));
@ -328,6 +332,8 @@ std::ostream& RecordSet::copyValues(std::ostream& os, std::size_t offset, std::s
void RecordSet::formatValues(std::size_t offset, std::size_t length) const
{
if (begin() == end()) return;
RowIterator it = *_pBegin + offset;
RowIterator end = (RowIterator::POSITION_END != length) ? it + length : *_pEnd;
std::string val;
@ -337,6 +343,8 @@ void RecordSet::formatValues(std::size_t offset, std::size_t length) const
std::ostream& RecordSet::copy(std::ostream& os, std::size_t offset, std::size_t length) const
{
if (begin() == end()) return os;
RowFormatter& rf = const_cast<RowFormatter&>((*_pBegin)->getFormatter());
rf.setTotalRowCount(static_cast<int>(getTotalRowCount()));
if (RowFormatter::FORMAT_PROGRESSIVE == rf.getMode())

View File

@ -22,6 +22,7 @@
#include "Poco/Data/Date.h"
#include "Poco/Data/Time.h"
#include "Poco/Data/SimpleRowFormatter.h"
#include "Poco/Data/JSONRowFormatter.h"
#include "Poco/Data/DataException.h"
#include "Connector.h"
#include "Poco/BinaryReader.h"
@ -64,7 +65,9 @@ using Poco::Data::CLOBOutputStream;
using Poco::Data::MetaColumn;
using Poco::Data::Column;
using Poco::Data::Row;
using Poco::Data::RowFormatter;
using Poco::Data::SimpleRowFormatter;
using Poco::Data::JSONRowFormatter;
using Poco::Data::Date;
using Poco::Data::Time;
using Poco::Data::AbstractExtraction;
@ -1166,7 +1169,7 @@ void DataTest::testRowStrictWeak(const Row& row1, const Row& row2, const Row& ro
}
void DataTest::testRowFormat()
void DataTest::testSimpleRowFormatter()
{
Row row1;
row1.append("field0", 0);
@ -1210,6 +1213,40 @@ void DataTest::testRowFormat()
}
void DataTest::testJSONRowFormatter()
{
Row row1;
row1.append("field0", 0);
row1.append("field1", "1");
row1.append("field2", DateTime(2007, 3, 13, 8, 12, 15));
row1.append("field3", Var());
row1.append("field4", 4);
row1.setFormatter(new JSONRowFormatter);
assert(row1.getFormatter().prefix() == "{");
assert(row1.getFormatter().postfix() == "]}");
assert(row1.getFormatter().getMode() == RowFormatter::FORMAT_PROGRESSIVE);
assert(row1.namesToString() == "\"names\":[\"field0\",\"field1\",\"field2\",\"field3\",\"field4\"]");
assert(row1.valuesToString() == ",\"values\":[[0,\"1\",\"2007-03-13T08:12:15Z\",null,4]");
row1.setFormatter(new JSONRowFormatter(JSONRowFormatter::JSON_FMT_MODE_SMALL));
assert(row1.getFormatter().getMode() == RowFormatter::FORMAT_PROGRESSIVE);
assert(row1.namesToString() == "");
//std::cout << row1.valuesToString() << std::endl;
assert(row1.valuesToString() == "[[0,\"1\",\"2007-03-13T08:12:15Z\",null,4]");
assert(row1.valuesToString() == ",[0,\"1\",\"2007-03-13T08:12:15Z\",null,4]");
row1.setFormatter(new JSONRowFormatter(JSONRowFormatter::JSON_FMT_MODE_FULL));
assert(row1.getFormatter().prefix() == "{\"count\":0,[");
assert(row1.getFormatter().postfix() == "]}");
assert(row1.getFormatter().getMode() == RowFormatter::FORMAT_PROGRESSIVE);
std::cout << row1.namesToString() << std::endl;
assert(row1.namesToString() == "");
assert(row1.valuesToString() == "{\"field0\":0,\"field1\":\"1\",\"field2\":\"2007-03-13T08:12:15Z\",\"field3\":null,\"field4\":4}");
assert(row1.valuesToString() == ",{\"field0\":0,\"field1\":\"1\",\"field2\":\"2007-03-13T08:12:15Z\",\"field3\":null,\"field4\":4}");
}
void DataTest::testDateAndTime()
{
DateTime dt;
@ -1399,7 +1436,8 @@ CppUnit::Test* DataTest::suite()
CppUnit_addTest(pSuite, DataTest, testColumnList);
CppUnit_addTest(pSuite, DataTest, testRow);
CppUnit_addTest(pSuite, DataTest, testRowSort);
CppUnit_addTest(pSuite, DataTest, testRowFormat);
CppUnit_addTest(pSuite, DataTest, testSimpleRowFormatter);
CppUnit_addTest(pSuite, DataTest, testJSONRowFormatter);
CppUnit_addTest(pSuite, DataTest, testDateAndTime);
CppUnit_addTest(pSuite, DataTest, testExternalBindingAndExtraction);

View File

@ -42,7 +42,8 @@ public:
void testColumnList();
void testRow();
void testRowSort();
void testRowFormat();
void testSimpleRowFormatter();
void testJSONRowFormatter();
void testDateAndTime();
void testExternalBindingAndExtraction();

View File

@ -502,6 +502,15 @@ public:
bool isString() const;
/// Returns true if stored value is std::string.
bool isDate() const;
/// Returns true if stored value represents a date.
bool isTime() const;
/// Returns true if stored value represents time or date/time.
bool isDateTime() const;
/// Returns true if stored value represents a date/time.
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)
@ -844,6 +853,27 @@ inline bool Var::isString() const
}
inline bool Var::isDate() const
{
VarHolder* pHolder = content();
return pHolder ? pHolder->isDate() : false;
}
inline bool Var::isTime() const
{
VarHolder* pHolder = content();
return pHolder ? pHolder->isTime() : false;
}
inline bool Var::isDateTime() const
{
VarHolder* pHolder = content();
return pHolder ? pHolder->isDateTime() : false;
}
inline std::size_t Var::size() const
{
VarHolder* pHolder = content();

View File

@ -254,6 +254,18 @@ public:
/// Returns false. Must be properly overriden in a type
/// specialization in order to suport the diagnostic.
virtual bool isDate() const;
/// Returns false. Must be properly overriden in a type
/// specialization in order to suport the diagnostic.
virtual bool isTime() const;
/// Returns false. Must be properly overriden in a type
/// specialization in order to suport the diagnostic.
virtual bool isDateTime() const;
/// Returns false. Must be properly overriden in a type
/// specialization in order to suport the diagnostic.
virtual std::size_t size() const;
/// Returns 1 iff Var is not empty or this function overriden.
@ -609,6 +621,24 @@ inline bool VarHolder::isString() const
return false;
}
inline bool VarHolder::isDate() const
{
return false;
}
inline bool VarHolder::isTime() const
{
return false;
}
inline bool VarHolder::isDateTime() const
{
return false;
}
inline std::size_t VarHolder::size() const
{
return 1u;
@ -3331,6 +3361,21 @@ public:
return false;
}
bool isDate() const
{
return true;
}
bool isTime() const
{
return true;
}
bool isDateTime() const
{
return true;
}
private:
VarHolderImpl();
VarHolderImpl(const VarHolderImpl&);
@ -3432,6 +3477,21 @@ public:
return false;
}
bool isDate() const
{
return true;
}
bool isTime() const
{
return true;
}
bool isDateTime() const
{
return true;
}
private:
VarHolderImpl();
VarHolderImpl(const VarHolderImpl&);
@ -3533,6 +3593,21 @@ public:
return false;
}
bool isDate() const
{
return true;
}
bool isTime() const
{
return true;
}
bool isDateTime() const
{
return true;
}
private:
VarHolderImpl();
VarHolderImpl(const VarHolderImpl&);

View File

@ -2392,8 +2392,17 @@ void VarTest::testDate()
Poco::Timestamp tsNow = dtNow.timestamp();
Poco::LocalDateTime ldtNow(dtNow.timestamp());
Var dt(dtNow);
assert(dt.isDate());
assert(dt.isTime());
assert(dt.isDateTime());
Var ts(tsNow);
assert(ts.isDate());
assert(ts.isTime());
assert(ts.isDateTime());
Var ldt(ldtNow);
assert(ldt.isDate());
assert(ldt.isTime());
assert(ldt.isDateTime());
Var dtStr(dt.convert<std::string>());
Var tsStr(ts.convert<std::string>());
Var ldtStr(ldt.convert<std::string>());