mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-24 17:30:44 +02:00
ODBC generic nulls, added Row and RowIterator
This commit is contained in:
@@ -293,6 +293,14 @@
|
||||
RelativePath=".\include\Poco\Data\RecordSet.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\Row.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\RowIterator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\Session.h"
|
||||
>
|
||||
@@ -381,6 +389,14 @@
|
||||
RelativePath=".\src\RecordSet.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Row.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\RowIterator.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Session.cpp"
|
||||
>
|
||||
|
||||
@@ -215,22 +215,23 @@ void Binder::bind(std::size_t pos, const NullData& val, Direction dir)
|
||||
|
||||
switch (val)
|
||||
{
|
||||
case NULL_INT8: bindNull(pos, SQL_C_STINYINT); break;
|
||||
case NULL_UINT8: bindNull(pos, SQL_C_UTINYINT); break;
|
||||
case NULL_INT16: bindNull(pos, SQL_C_SSHORT); break;
|
||||
case NULL_UINT16: bindNull(pos, SQL_C_USHORT); break;
|
||||
case NULL_INT32: bindNull(pos, SQL_C_SLONG); break;
|
||||
case NULL_UINT32: bindNull(pos, SQL_C_ULONG); break;
|
||||
case NULL_INT64: bindNull(pos, SQL_C_SBIGINT); break;
|
||||
case NULL_UINT64: bindNull(pos, SQL_C_UBIGINT); break;
|
||||
case NULL_BOOL: bindNull(pos, Utility::boolDataType); break;
|
||||
case NULL_FLOAT: bindNull(pos, SQL_C_FLOAT); break;
|
||||
case NULL_DOUBLE: bindNull(pos, SQL_C_DOUBLE); break;
|
||||
case NULL_STRING: bindNull(pos, SQL_C_CHAR); break;
|
||||
case NULL_BLOB: bindNull(pos, SQL_C_BINARY); break;
|
||||
case NULL_TIMESTAMP: bindNull(pos, SQL_C_TIMESTAMP); break;
|
||||
case NULL_GENERIC:
|
||||
case NULL_INT8: bindNull(pos, SQL_C_STINYINT); break;
|
||||
case NULL_UINT8: bindNull(pos, SQL_C_UTINYINT); break;
|
||||
case NULL_INT16: bindNull(pos, SQL_C_SSHORT); break;
|
||||
case NULL_UINT16: bindNull(pos, SQL_C_USHORT); break;
|
||||
case NULL_INT32: bindNull(pos, SQL_C_SLONG); break;
|
||||
case NULL_UINT32: bindNull(pos, SQL_C_ULONG); break;
|
||||
case NULL_INT64: bindNull(pos, SQL_C_SBIGINT); break;
|
||||
case NULL_UINT64: bindNull(pos, SQL_C_UBIGINT); break;
|
||||
case NULL_BOOL: bindNull(pos, Utility::boolDataType); break;
|
||||
case NULL_FLOAT: bindNull(pos, SQL_C_FLOAT); break;
|
||||
case NULL_DOUBLE: bindNull(pos, SQL_C_DOUBLE); break;
|
||||
case NULL_STRING: bindNull(pos, SQL_C_CHAR); break;
|
||||
case NULL_BLOB: bindNull(pos, SQL_C_BINARY); break;
|
||||
case NULL_TIMESTAMP: bindNull(pos, SQL_C_TIMESTAMP); break;
|
||||
|
||||
default:
|
||||
default:
|
||||
throw DataFormatException("Unsupported data type.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2068,7 +2068,7 @@ void SQLExecutor::notNulls(const std::string& sqlState)
|
||||
{
|
||||
try
|
||||
{
|
||||
*_pSession << "INSERT INTO NullTest (i,r,v) VALUES (?,?,?)", use(NULL_INT8), use(NULL_FLOAT), use(NULL_STRING), now;
|
||||
*_pSession << "INSERT INTO NullTest (i,r,v) VALUES (?,?,?)", use(null), use(null), use(null), now;
|
||||
fail ("must fail");
|
||||
}catch (StatementException& se)
|
||||
{
|
||||
@@ -2083,7 +2083,7 @@ void SQLExecutor::nulls()
|
||||
{
|
||||
std::string funct = "nulls()";
|
||||
|
||||
try { *_pSession << "INSERT INTO NullTest (i,r,v) VALUES (?,?,?)", use(NULL_INT32), use(NULL_FLOAT), use(NULL_STRING), now; }
|
||||
try { *_pSession << "INSERT INTO NullTest (i,r,v) VALUES (?,?,?)", use(null), use(null), use(null), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
|
||||
@@ -2115,12 +2115,12 @@ void SQLExecutor::nulls()
|
||||
assert (!rs.isNull("r"));
|
||||
assert (rs["v"] == "123");
|
||||
|
||||
try { *_pSession << "UPDATE NullTest SET v = ? WHERE i = ?", use(NULL_STRING), use(i), now; }
|
||||
try { *_pSession << "UPDATE NullTest SET v = ? WHERE i = ?", use(null), use(i), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
i = 2;
|
||||
f = 3.4;
|
||||
try { *_pSession << "INSERT INTO NullTest (i, r, v) VALUES (?,?,?)", use(i), use(NULL_FLOAT), use(NULL_STRING), now; }
|
||||
try { *_pSession << "INSERT INTO NullTest (i, r, v) VALUES (?,?,?)", use(i), use(null), use(null), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
rs = (*_pSession << "SELECT i, r, v FROM NullTest ORDER BY i ASC", now);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "Poco/Data/Data.h"
|
||||
#include "Poco/Data/Extraction.h"
|
||||
#include "Poco/Data/Statement.h"
|
||||
#include "Poco/Data/RowIterator.h"
|
||||
#include "Poco/Data/BLOB.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
@@ -58,7 +59,7 @@ class Session;
|
||||
|
||||
class Data_API RecordSet: private Statement
|
||||
/// RecordSet provides access to data returned from a query.
|
||||
/// Data access indexes (row and column) are 0-based, as usual in C++.
|
||||
/// Data access indices (row and column) are 0-based, as usual in C++.
|
||||
///
|
||||
/// Recordset provides navigation methods to iterate through the
|
||||
/// recordset, retrieval methods to extract data, and methods
|
||||
@@ -76,6 +77,8 @@ class Data_API RecordSet: private Statement
|
||||
/// a limit for the Statement.
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::size_t, Row*> RowMap;
|
||||
|
||||
using Statement::isNull;
|
||||
|
||||
explicit RecordSet(const Statement& rStatement);
|
||||
@@ -129,6 +132,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
const Row& row(std::size_t pos) const;
|
||||
/// Returns row at position pos.
|
||||
/// Rows are lazy-created and cached.
|
||||
|
||||
template <class T>
|
||||
const T& value(std::size_t col, std::size_t row) const
|
||||
/// Returns the reference to data value at [col, row] location.
|
||||
@@ -166,10 +173,13 @@ public:
|
||||
}
|
||||
|
||||
DynamicAny value(std::size_t col, std::size_t row) const;
|
||||
/// Returns the reference to data value at column, row location.
|
||||
/// Returns the data value at column, row location.
|
||||
|
||||
DynamicAny value(const std::string& name, std::size_t row) const;
|
||||
/// Returns the reference to data value at named column, row location.
|
||||
/// Returns the data value at named column, row location.
|
||||
|
||||
const RowIterator& begin();
|
||||
/// Moves the row cursor to the first row and returns the pointer to row.
|
||||
|
||||
bool moveFirst();
|
||||
/// Moves the row cursor to the first row.
|
||||
@@ -190,6 +200,9 @@ public:
|
||||
/// Returns true if the row is available, or false
|
||||
/// if there are no more rows available.
|
||||
|
||||
const RowIterator& end();
|
||||
/// Moves the row cursor to the last row and returns null pointer.
|
||||
|
||||
bool moveLast();
|
||||
/// Moves the row cursor to the last row.
|
||||
///
|
||||
@@ -262,7 +275,10 @@ private:
|
||||
throw NotFoundException(format("Unknown column name: %s", name));
|
||||
}
|
||||
|
||||
std::size_t _currentRow;
|
||||
std::size_t _currentRow;
|
||||
RowIterator* _pBegin;
|
||||
RowIterator* _pEnd;
|
||||
mutable RowMap _rowMap;
|
||||
};
|
||||
|
||||
|
||||
@@ -361,6 +377,15 @@ inline bool RecordSet::isNull(const std::string& name)
|
||||
}
|
||||
|
||||
|
||||
inline const RowIterator& RecordSet::end()
|
||||
{
|
||||
if (!_pEnd)
|
||||
_pEnd = new RowIterator(*this);
|
||||
|
||||
return *_pEnd;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
|
||||
|
||||
169
Data/include/Poco/Data/Row.h
Normal file
169
Data/include/Poco/Data/Row.h
Normal file
@@ -0,0 +1,169 @@
|
||||
//
|
||||
// Row.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/include/Poco/Data/Row.h#7 $
|
||||
//
|
||||
// Library: Data
|
||||
// Package: DataCore
|
||||
// Module: Row
|
||||
//
|
||||
// Definition of the Row class.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#ifndef Data_Row_INCLUDED
|
||||
#define Data_Row_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/Data.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
class RecordSet;
|
||||
|
||||
|
||||
class Data_API Row
|
||||
/// Row class.
|
||||
{
|
||||
public:
|
||||
enum Comparison
|
||||
{
|
||||
COMPARE_AS_INTEGER,
|
||||
COMPARE_AS_FLOAT,
|
||||
COMPARE_AS_STRING
|
||||
};
|
||||
|
||||
static const std::string EOL;
|
||||
|
||||
Row();
|
||||
/// Creates the Row.
|
||||
|
||||
~Row();
|
||||
/// Destroys the Row.
|
||||
|
||||
DynamicAny& operator [] (std::size_t col);
|
||||
/// Returns the reference to data value at column location.
|
||||
|
||||
DynamicAny& operator [] (const std::string& name);
|
||||
/// Returns the reference to data value at named column location.
|
||||
|
||||
template <typename T>
|
||||
void append(const std::string& name, const T& val)
|
||||
/// Appends the value to the row.
|
||||
{
|
||||
DynamicAny da = val;
|
||||
_values.push_back(da);
|
||||
_names.push_back(name);
|
||||
}
|
||||
|
||||
std::size_t fieldCount() const;
|
||||
/// Returns the number of fields in this row.
|
||||
|
||||
void reset();
|
||||
/// Resets the row.
|
||||
|
||||
void separator(const std::string& sep);
|
||||
/// Sets the separator.
|
||||
|
||||
void sortField(std::size_t pos);
|
||||
/// Sets the field used for sorting.
|
||||
|
||||
void sortField(const std::string& name);
|
||||
/// Sets the field used for sorting.
|
||||
|
||||
const std::string& toStringN() const;
|
||||
/// Converts the row names to string, inserting separator
|
||||
/// string between fields and end-of-line at the end.
|
||||
|
||||
const std::string& toStringV() const;
|
||||
/// Converts the row values to string, inserting separator
|
||||
/// string between fields and end-of-line at the end.
|
||||
|
||||
bool operator == (const Row& other) const;
|
||||
/// Equality operator.
|
||||
|
||||
bool operator != (const Row& other) const;
|
||||
/// Inequality operator.
|
||||
|
||||
bool operator < (const Row& other) const;
|
||||
/// Less-then operator.
|
||||
|
||||
void comparison(Comparison comp);
|
||||
/// Sets the type of comparison.
|
||||
|
||||
private:
|
||||
std::size_t getPosition(const std::string& name);
|
||||
bool isEqualSize(const Row& other) const;
|
||||
bool isEqualType(const Row& other) const;
|
||||
|
||||
std::vector<std::string> _names;
|
||||
std::vector<DynamicAny> _values;
|
||||
mutable std::string _strValues;
|
||||
mutable std::string _strNames;
|
||||
std::string _separator;
|
||||
std::size_t _sortField;
|
||||
Comparison _comparison;
|
||||
};
|
||||
|
||||
|
||||
Data_API std::ostream& operator << (std::ostream &os, const Row& row);
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
inline std::size_t Row::fieldCount() const
|
||||
{
|
||||
return _values.size();
|
||||
}
|
||||
|
||||
|
||||
inline void Row::reset()
|
||||
{
|
||||
_names.clear();
|
||||
_values.clear();
|
||||
}
|
||||
|
||||
|
||||
inline void Row::separator(const std::string& sep)
|
||||
{
|
||||
_separator = sep;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
|
||||
#endif // Data_Row_INCLUDED
|
||||
121
Data/include/Poco/Data/RowIterator.h
Normal file
121
Data/include/Poco/Data/RowIterator.h
Normal file
@@ -0,0 +1,121 @@
|
||||
//
|
||||
// RowIterator.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/include/Poco/Data/RowIterator.h#7 $
|
||||
//
|
||||
// Library: Data
|
||||
// Package: DataCore
|
||||
// Module: RowIterator
|
||||
//
|
||||
// Definition of the RowIterator class.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#ifndef Data_RowIterator_INCLUDED
|
||||
#define Data_RowIterator_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/Data.h"
|
||||
#include "Poco/Data/Row.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
class RecordSet;
|
||||
|
||||
|
||||
class Data_API RowIterator
|
||||
/// RowIterator class is an interface to a row of RecordSet data.
|
||||
{
|
||||
public:
|
||||
RowIterator(const RecordSet& recordSet, bool isEmpty = true);
|
||||
/// Creates the RowIterator and positions it at the beginning.
|
||||
|
||||
~RowIterator();
|
||||
/// Destroys the RowIterator.
|
||||
|
||||
bool operator == (const RowIterator& other);
|
||||
/// Equality operator.
|
||||
|
||||
bool operator != (const RowIterator& other);
|
||||
/// Inequality operator.
|
||||
|
||||
const Row& operator * () const;
|
||||
/// Returns const reference to the current row.
|
||||
|
||||
const Row& operator ++ ();
|
||||
/// Advances by one position and returns const reference
|
||||
/// to the current row.
|
||||
|
||||
const Row& operator ++ (int);
|
||||
/// Advances by one position and returns const reference
|
||||
/// to the previous current row.
|
||||
|
||||
const Row& operator -- ();
|
||||
/// Goes back by one position and returns const reference
|
||||
/// to the current row.
|
||||
|
||||
const Row& operator -- (int);
|
||||
/// Goes back by one position and returns const reference
|
||||
/// to the previous current row.
|
||||
|
||||
private:
|
||||
RowIterator();
|
||||
|
||||
void increment();
|
||||
void decrement();
|
||||
|
||||
static const int POSITION_END;
|
||||
|
||||
std::size_t _position;
|
||||
const RecordSet& _recordSet;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
inline bool RowIterator::operator == (const RowIterator& other)
|
||||
{
|
||||
return _position == other._position;
|
||||
}
|
||||
|
||||
|
||||
inline bool RowIterator::operator != (const RowIterator& other)
|
||||
{
|
||||
return _position != other._position;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
|
||||
#endif // Data_RowIterator_INCLUDED
|
||||
@@ -44,20 +44,31 @@ namespace Data {
|
||||
|
||||
RecordSet::RecordSet(const Statement& rStatement):
|
||||
Statement(rStatement),
|
||||
_currentRow(0)
|
||||
_currentRow(0),
|
||||
_pBegin(0),
|
||||
_pEnd(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RecordSet::RecordSet(Session& rSession, const std::string& query):
|
||||
Statement((rSession << query, now)),
|
||||
_currentRow(0)
|
||||
_currentRow(0),
|
||||
_pBegin(0),
|
||||
_pEnd(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RecordSet::~RecordSet()
|
||||
{
|
||||
delete _pBegin;
|
||||
delete _pEnd;
|
||||
|
||||
RowMap::iterator it = _rowMap.begin();
|
||||
RowMap::iterator end = _rowMap.end();
|
||||
for (; it != end; ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +118,36 @@ DynamicAny RecordSet::value(const std::string& name, std::size_t row) const
|
||||
}
|
||||
|
||||
|
||||
const RowIterator& RecordSet::begin()
|
||||
{
|
||||
if (!_pBegin)
|
||||
_pBegin = new RowIterator(*this, 0 == extractions().size());
|
||||
|
||||
return *_pBegin;
|
||||
}
|
||||
|
||||
|
||||
const Row& RecordSet::row(std::size_t pos) const
|
||||
{
|
||||
if (pos > rowCount() - 1)
|
||||
throw RangeException("Invalid recordset row requested.");
|
||||
|
||||
RowMap::iterator it = _rowMap.find(pos);
|
||||
Row* pRow = 0;
|
||||
if (it == _rowMap.end())
|
||||
{
|
||||
pRow = new Row;
|
||||
for (std::size_t i = 0; i < columnCount(); ++i)
|
||||
pRow->append(metaColumn(static_cast<UInt32>(pos)).name(), value(i, pos));
|
||||
|
||||
_rowMap.insert(RowMap::value_type(pos, pRow));
|
||||
}
|
||||
|
||||
poco_check_ptr (pRow);
|
||||
return *pRow;
|
||||
}
|
||||
|
||||
|
||||
bool RecordSet::moveFirst()
|
||||
{
|
||||
if (rowCount() > 0)
|
||||
|
||||
245
Data/src/Row.cpp
Normal file
245
Data/src/Row.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
//
|
||||
// Row.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/src/Row.cpp#2 $
|
||||
//
|
||||
// Library: Data
|
||||
// Package: DataCore
|
||||
// Module: Row
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/Row.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
const std::string Row::EOL = "\r\n";
|
||||
#else
|
||||
const std::string Row::EOL = "\n";
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
std::ostream& operator << (std::ostream &os, const Row& row)
|
||||
{
|
||||
os << row.toStringV();
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
Row::Row():
|
||||
_separator("\t"),
|
||||
_sortField(0),
|
||||
_comparison(COMPARE_AS_STRING)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Row::~Row()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DynamicAny& Row::operator [] (std::size_t col)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _values.at(col);
|
||||
}catch (std::range_error& re)
|
||||
{
|
||||
throw RangeException(re.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DynamicAny& Row::operator [] (const std::string& name)
|
||||
{
|
||||
std::size_t col = getPosition(name);
|
||||
return (*this)[col];
|
||||
}
|
||||
|
||||
|
||||
std::size_t Row::getPosition(const std::string& name)
|
||||
{
|
||||
std::vector<std::string>::const_iterator it = _names.begin();
|
||||
std::vector<std::string>::const_iterator end = _names.end();
|
||||
std::size_t col = 0;
|
||||
for (; it != end; ++it, ++col)
|
||||
if (name == *it) break;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
|
||||
void Row::sortField(std::size_t pos)
|
||||
{
|
||||
poco_assert (pos <= _values.size());
|
||||
_sortField = pos;
|
||||
|
||||
if ((_values[pos].type() == typeid(Poco::Int8)) ||
|
||||
(_values[pos].type() == typeid(Poco::UInt8)) ||
|
||||
(_values[pos].type() == typeid(Poco::Int16)) ||
|
||||
(_values[pos].type() == typeid(Poco::UInt16)) ||
|
||||
(_values[pos].type() == typeid(Poco::Int32)) ||
|
||||
(_values[pos].type() == typeid(Poco::UInt32)) ||
|
||||
(_values[pos].type() == typeid(Poco::Int64)) ||
|
||||
(_values[pos].type() == typeid(Poco::UInt64)) ||
|
||||
(_values[pos].type() == typeid(bool)))
|
||||
{
|
||||
comparison(COMPARE_AS_INTEGER);
|
||||
}
|
||||
else if ((_values[pos].type() == typeid(float)) ||
|
||||
(_values[pos].type() == typeid(double)))
|
||||
{
|
||||
comparison(COMPARE_AS_FLOAT);
|
||||
}
|
||||
else
|
||||
{
|
||||
comparison(COMPARE_AS_STRING);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Row::sortField(const std::string& name)
|
||||
{
|
||||
sortField(getPosition(name));
|
||||
}
|
||||
|
||||
|
||||
bool Row::isEqualSize(const Row& other) const
|
||||
{
|
||||
return (other._values.size() == _values.size());
|
||||
}
|
||||
|
||||
|
||||
bool Row::isEqualType(const Row& other) const
|
||||
{
|
||||
std::vector<DynamicAny>::const_iterator it = _values.begin();
|
||||
std::vector<DynamicAny>::const_iterator end = _values.end();
|
||||
for (int i = 0; it != end; ++it, ++i)
|
||||
{
|
||||
if (it->type() != other._values[i].type())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Row::comparison(Comparison comp)
|
||||
{
|
||||
_comparison = comp;
|
||||
}
|
||||
|
||||
|
||||
bool Row::operator == (const Row& other) const
|
||||
{
|
||||
if (!isEqualSize(other)) return false;
|
||||
if (!isEqualType(other)) return false;
|
||||
|
||||
std::vector<DynamicAny>::const_iterator it = _values.begin();
|
||||
std::vector<DynamicAny>::const_iterator end = _values.end();
|
||||
for (int i = 0; it != end; ++it, ++i)
|
||||
{
|
||||
if ((*it).convert<std::string>() != other._values[i].convert<std::string>())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Row::operator != (const Row& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
bool Row::operator < (const Row& other) const
|
||||
{
|
||||
if (_sortField != other._sortField)
|
||||
throw InvalidAccessException("Rows compared have different sorting criteria.");
|
||||
|
||||
switch (_comparison)
|
||||
{
|
||||
case COMPARE_AS_INTEGER:
|
||||
return (_values[_sortField].convert<Poco::Int64>() <
|
||||
other._values[other._sortField].convert<Poco::Int64>());
|
||||
|
||||
case COMPARE_AS_FLOAT:
|
||||
return (_values[_sortField].convert<double>() <
|
||||
other._values[other._sortField].convert<double>());
|
||||
|
||||
case COMPARE_AS_STRING:
|
||||
return (_values[_sortField].convert<std::string>() <
|
||||
other._values[other._sortField].convert<std::string>());
|
||||
}
|
||||
|
||||
throw IllegalStateException("Unknown comparison mode.");
|
||||
}
|
||||
|
||||
|
||||
const std::string& Row::toStringV() const
|
||||
{
|
||||
_strValues.clear();
|
||||
std::vector<DynamicAny>::const_iterator it = _values.begin();
|
||||
std::vector<DynamicAny>::const_iterator end = _values.end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
_strValues.append(it->convert<std::string>());
|
||||
_strValues.append(_separator);
|
||||
}
|
||||
_strValues.replace(_strValues.find_last_of(_separator), _separator.length(), EOL);
|
||||
|
||||
return _strValues;
|
||||
}
|
||||
|
||||
|
||||
const std::string& Row::toStringN() const
|
||||
{
|
||||
_strNames.clear();
|
||||
std::vector<std::string>::const_iterator it = _names.begin();
|
||||
std::vector<std::string>::const_iterator end = _names.end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
_strNames.append(*it);
|
||||
_strNames.append(_separator);
|
||||
}
|
||||
_strNames.replace(_strNames.find_last_of(_separator), _separator.length(), EOL);
|
||||
|
||||
return _strNames;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
118
Data/src/RowIterator.cpp
Normal file
118
Data/src/RowIterator.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// RowIterator.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/src/RowIterator.cpp#2 $
|
||||
//
|
||||
// Library: Data
|
||||
// Package: DataCore
|
||||
// Module: RowIterator
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/RowIterator.h"
|
||||
#include "Poco/Data/RecordSet.h"
|
||||
#undef min
|
||||
#undef max
|
||||
#include <limits>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
const int RowIterator::POSITION_END = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
|
||||
RowIterator::RowIterator(const RecordSet& recordSet, bool isEmpty):
|
||||
_position(isEmpty ? POSITION_END : 0),
|
||||
_recordSet(recordSet)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RowIterator::~RowIterator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void RowIterator::increment()
|
||||
{
|
||||
if (POSITION_END == _position)
|
||||
throw RangeException("End of iterator reached.");
|
||||
|
||||
if (_position < _recordSet.rowCount() - 1)
|
||||
++_position;
|
||||
else
|
||||
_position = POSITION_END;
|
||||
}
|
||||
|
||||
|
||||
void RowIterator::decrement()
|
||||
{
|
||||
if (0 == _position)
|
||||
throw RangeException("End of iterator reached.");
|
||||
|
||||
--_position;
|
||||
}
|
||||
|
||||
|
||||
const Row& RowIterator::operator * () const
|
||||
{
|
||||
return _recordSet.row(_position);
|
||||
}
|
||||
|
||||
|
||||
const Row& RowIterator::operator ++ ()
|
||||
{
|
||||
increment();
|
||||
return _recordSet.row(_position);
|
||||
}
|
||||
|
||||
|
||||
const Row& RowIterator::operator ++ (int)
|
||||
{
|
||||
increment();
|
||||
return _recordSet.row(_position - 1);
|
||||
}
|
||||
|
||||
|
||||
const Row& RowIterator::operator -- ()
|
||||
{
|
||||
decrement();
|
||||
return _recordSet.row(_position);
|
||||
}
|
||||
|
||||
|
||||
const Row& RowIterator::operator -- (int)
|
||||
{
|
||||
decrement();
|
||||
return _recordSet.row(_position + 1);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
@@ -38,12 +38,15 @@
|
||||
#include "Poco/Data/BLOBStream.h"
|
||||
#include "Poco/Data/MetaColumn.h"
|
||||
#include "Poco/Data/Column.h"
|
||||
#include "Poco/Data/Row.h"
|
||||
#include "Connector.h"
|
||||
#include "Poco/BinaryReader.h"
|
||||
#include "Poco/BinaryWriter.h"
|
||||
#include "Poco/Types.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
|
||||
using namespace Poco::Data;
|
||||
@@ -570,6 +573,84 @@ void DataTest::testColumnList()
|
||||
}
|
||||
|
||||
|
||||
void DataTest::testRow()
|
||||
{
|
||||
Row row;
|
||||
|
||||
row.append("field0", 0);
|
||||
row.append("field1", 1);
|
||||
row.append("field2", 2);
|
||||
row.append("field3", 3);
|
||||
row.append("field4", 4);
|
||||
|
||||
assert (5 == row.fieldCount());
|
||||
assert (row[0] == 0);
|
||||
assert (row["field0"] == 0);
|
||||
assert (row[1] == 1);
|
||||
assert (row["field1"] == 1);
|
||||
assert (row[2] == 2);
|
||||
assert (row["field2"] == 2);
|
||||
assert (row[3] == 3);
|
||||
assert (row["field3"] == 3);
|
||||
assert (row[4] == 4);
|
||||
assert (row["field4"] == 4);
|
||||
|
||||
assert (row.toStringN() == std::string("field0\tfield1\tfield2\tfield3\tfield4") + Row::EOL);
|
||||
std::ostringstream os;
|
||||
os << row;
|
||||
assert (os.str() == std::string("0\t1\t2\t3\t4") + Row::EOL);
|
||||
row.separator(",");
|
||||
assert (row.toStringN() == std::string("field0,field1,field2,field3,field4") + Row::EOL);
|
||||
os.str("");
|
||||
os << row;
|
||||
assert (os.str() == std::string("0,1,2,3,4") + Row::EOL);
|
||||
|
||||
Row row2;
|
||||
|
||||
row2.append("field0", 5);
|
||||
row2.append("field1", 4);
|
||||
row2.append("field2", 3);
|
||||
row2.append("field3", 2);
|
||||
row2.append("field4", 1);
|
||||
|
||||
assert (row != row2);
|
||||
|
||||
std::map<Row, int> rowMap;
|
||||
rowMap.insert(std::map<Row, int>::value_type(row2, 0));
|
||||
rowMap.insert(std::map<Row, int>::value_type(row, 1));
|
||||
std::map<Row, int>::iterator it = rowMap.begin();
|
||||
assert (row == it->first);
|
||||
++it;
|
||||
assert (row2 == it->first);
|
||||
|
||||
rowMap.clear();
|
||||
row.sortField("field4");
|
||||
rowMap.insert(std::map<Row, int>::value_type(row, 0));
|
||||
try
|
||||
{
|
||||
rowMap.insert(std::map<Row, int>::value_type(row2, 1));
|
||||
fail ("must fail");
|
||||
}catch (InvalidAccessException&) {}
|
||||
|
||||
row2.sortField("field4");
|
||||
rowMap.insert(std::map<Row, int>::value_type(row2, 1));
|
||||
it = rowMap.begin();
|
||||
assert (row2 == it->first);
|
||||
++it;
|
||||
assert (row == it->first);
|
||||
|
||||
Row row3;
|
||||
|
||||
row3.append("field0", 0);
|
||||
row3.append("field1", 1);
|
||||
row3.append("field2", 2);
|
||||
row3.append("field3", 3);
|
||||
row3.append("field4", 4);
|
||||
|
||||
assert (row3 == row);
|
||||
}
|
||||
|
||||
|
||||
void DataTest::setUp()
|
||||
{
|
||||
}
|
||||
@@ -592,6 +673,7 @@ CppUnit::Test* DataTest::suite()
|
||||
CppUnit_addTest(pSuite, DataTest, testColumnVector);
|
||||
CppUnit_addTest(pSuite, DataTest, testColumnDeque);
|
||||
CppUnit_addTest(pSuite, DataTest, testColumnList);
|
||||
CppUnit_addTest(pSuite, DataTest, testRow);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ public:
|
||||
void testColumnVector();
|
||||
void testColumnDeque();
|
||||
void testColumnList();
|
||||
void testRow();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
Reference in New Issue
Block a user