mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-24 00:49:46 +02:00
improved support for multiple statement execution and recordset paging
This commit is contained in:
@@ -50,6 +50,7 @@
|
|||||||
#include "Poco/Dynamic/Var.h"
|
#include "Poco/Dynamic/Var.h"
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@@ -93,8 +94,12 @@ public:
|
|||||||
|
|
||||||
using Statement::isNull;
|
using Statement::isNull;
|
||||||
using Statement::setRowFormatter;
|
using Statement::setRowFormatter;
|
||||||
|
using Statement::subTotalRowCount;
|
||||||
|
|
||||||
explicit RecordSet(const Statement& rStatement);
|
static const std::size_t UNKNOWN_TOTAL_ROW_COUNT;
|
||||||
|
|
||||||
|
explicit RecordSet(const Statement& rStatement,
|
||||||
|
RowFormatter* pRowFormatter = 0);
|
||||||
/// Creates the RecordSet.
|
/// Creates the RecordSet.
|
||||||
|
|
||||||
explicit RecordSet(Session& rSession,
|
explicit RecordSet(Session& rSession,
|
||||||
@@ -119,9 +124,31 @@ public:
|
|||||||
/// for large recordsets, so it should be used judiciously.
|
/// for large recordsets, so it should be used judiciously.
|
||||||
/// Use totalRowCount() to obtain the total number of rows.
|
/// Use totalRowCount() to obtain the total number of rows.
|
||||||
|
|
||||||
|
std::size_t extractedRowCount() const;
|
||||||
|
/// Returns the number of rows extracted during the last statement
|
||||||
|
/// execution.
|
||||||
|
/// The number of rows reported is independent of filtering.
|
||||||
|
|
||||||
std::size_t totalRowCount() const;
|
std::size_t totalRowCount() const;
|
||||||
|
//@ deprecated
|
||||||
|
/// Replaced with subTotalRowCount() and getTotalRowCount().
|
||||||
|
|
||||||
|
std::size_t getTotalRowCount() const;
|
||||||
/// Returns the total number of rows in the RecordSet.
|
/// Returns the total number of rows in the RecordSet.
|
||||||
/// The number of rows reported is independent of filtering.
|
/// The number of rows reported is independent of filtering.
|
||||||
|
/// If the total row count has not been set externally
|
||||||
|
/// (either explicitly or implicitly through SQL), the value
|
||||||
|
/// returned shall only be accurate if the statement limit
|
||||||
|
/// is less or equal to the total row count.
|
||||||
|
|
||||||
|
void setTotalRowCount(std::size_t totalRowCount);
|
||||||
|
/// Explicitly sets the total row count.
|
||||||
|
|
||||||
|
void setTotalRowCount(const std::string& sql);
|
||||||
|
/// Implicitly sets the total row count.
|
||||||
|
/// The supplied sql must return exactly one column
|
||||||
|
/// and one row. The returned value must be an unsigned
|
||||||
|
/// integer. The value is set as the total number of rows.
|
||||||
|
|
||||||
std::size_t columnCount() const;
|
std::size_t columnCount() const;
|
||||||
/// Returns the number of columns in the recordset.
|
/// Returns the number of columns in the recordset.
|
||||||
@@ -340,7 +367,9 @@ public:
|
|||||||
/// cause RangeException to be thrown.
|
/// cause RangeException to be thrown.
|
||||||
/// Copied string is formatted by the current RowFormatter.
|
/// Copied string is formatted by the current RowFormatter.
|
||||||
|
|
||||||
std::ostream& copy(std::ostream& os) const;
|
std::ostream& copy(std::ostream& os,
|
||||||
|
std::size_t offset = 0,
|
||||||
|
std::size_t length = RowIterator::POSITION_END) const;
|
||||||
/// Copies the column names and values to the target output stream.
|
/// Copies the column names and values to the target output stream.
|
||||||
/// Copied strings are formatted by the current RowFormatter.
|
/// Copied strings are formatted by the current RowFormatter.
|
||||||
|
|
||||||
@@ -432,6 +461,7 @@ private:
|
|||||||
RowIterator* _pEnd;
|
RowIterator* _pEnd;
|
||||||
RowMap _rowMap;
|
RowMap _rowMap;
|
||||||
RowFilter* _pFilter;
|
RowFilter* _pFilter;
|
||||||
|
std::size_t _totalRowCount;
|
||||||
|
|
||||||
friend class RowIterator;
|
friend class RowIterator;
|
||||||
friend class RowFilter;
|
friend class RowFilter;
|
||||||
@@ -448,7 +478,28 @@ inline Data_API std::ostream& operator << (std::ostream &os, const RecordSet& rs
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline std::size_t RecordSet::getTotalRowCount() const
|
||||||
|
{
|
||||||
|
if (UNKNOWN_TOTAL_ROW_COUNT == _totalRowCount)
|
||||||
|
return subTotalRowCount();
|
||||||
|
else
|
||||||
|
return _totalRowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline std::size_t RecordSet::totalRowCount() const
|
inline std::size_t RecordSet::totalRowCount() const
|
||||||
|
{
|
||||||
|
return getTotalRowCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void RecordSet::setTotalRowCount(std::size_t totalRowCount)
|
||||||
|
{
|
||||||
|
_totalRowCount = totalRowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline std::size_t RecordSet::extractedRowCount() const
|
||||||
{
|
{
|
||||||
return rowsExtracted();
|
return rowsExtracted();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ public:
|
|||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
/// Returns true if there is not filtering criteria specified.
|
/// Returns true if there is not filtering criteria specified.
|
||||||
|
|
||||||
bool isAllowed(std::size_t row) const;//const std::string& name, const Poco::Dynamic::Var& val) const;
|
bool isAllowed(std::size_t row) const;
|
||||||
/// Returns true if name and value are allowed.
|
/// Returns true if name and value are allowed.
|
||||||
|
|
||||||
bool exists(const std::string& name) const;
|
bool exists(const std::string& name) const;
|
||||||
|
|||||||
@@ -75,7 +75,9 @@ class Data_API RowFormatter
|
|||||||
public:
|
public:
|
||||||
typedef std::vector<std::string> NameVec;
|
typedef std::vector<std::string> NameVec;
|
||||||
typedef SharedPtr<std::vector<std::string> > NameVecPtr;
|
typedef SharedPtr<std::vector<std::string> > NameVecPtr;
|
||||||
typedef std::vector<Poco::Dynamic::Var> ValueVec;
|
typedef std::vector<Poco::Dynamic::Var> ValueVec;
|
||||||
|
|
||||||
|
static const int INVALID_ROW_COUNT = -1;
|
||||||
|
|
||||||
RowFormatter(const std::string& prefix = "", const std::string& postfix = "");
|
RowFormatter(const std::string& prefix = "", const std::string& postfix = "");
|
||||||
/// Creates the RowFormatter and sets the prefix and postfix to specified values.
|
/// Creates the RowFormatter and sets the prefix and postfix to specified values.
|
||||||
@@ -89,34 +91,72 @@ public:
|
|||||||
virtual std::string& formatValues(const ValueVec& vals, std::string& formattedValues) const = 0;
|
virtual std::string& formatValues(const ValueVec& vals, std::string& formattedValues) const = 0;
|
||||||
/// Formats the row values.
|
/// Formats the row values.
|
||||||
|
|
||||||
|
virtual int rowCount() const;
|
||||||
|
/// Returns INVALID_ROW_COUNT. Must be implemented by inheriting classes
|
||||||
|
/// which maintain count of processed rows.
|
||||||
|
|
||||||
|
int getTotalRowCount() const;
|
||||||
|
/// Returns zero. Must be implemented by inheriting classes.
|
||||||
|
/// Typically, total row count shall be set up front through
|
||||||
|
/// setTotalRowCount() call.
|
||||||
|
|
||||||
|
void setTotalRowCount(int count);
|
||||||
|
/// Sets total row count.
|
||||||
|
|
||||||
const std::string& prefix() const;
|
const std::string& prefix() const;
|
||||||
/// Returns prefix string;
|
/// Returns prefix string;
|
||||||
|
|
||||||
const std::string& postfix() const;
|
const std::string& postfix() const;
|
||||||
/// Returns postfix string;
|
/// Returns postfix string;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
/// Resets the formatter by setting prefix and postfix
|
||||||
|
/// to empty strings and row count to INVALID_ROW_COUNT.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setPrefix(const std::string& prefix);
|
|
||||||
void setPostfix(const std::string& postfix);
|
void setPrefix(const std::string& prefix) const;
|
||||||
|
/// Sets the p[refix for the formatter.
|
||||||
|
|
||||||
|
void setPostfix(const std::string& postfix) const;
|
||||||
|
/// Sets the postfix for the formatter
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _prefix;
|
|
||||||
std::string _postfix;
|
mutable std::string _prefix;
|
||||||
|
mutable std::string _postfix;
|
||||||
|
int _totalRowCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// inlines
|
/// inlines
|
||||||
///
|
///
|
||||||
|
inline int RowFormatter::rowCount() const
|
||||||
|
{
|
||||||
|
return INVALID_ROW_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void RowFormatter::setPrefix(const std::string& prefix)
|
inline int RowFormatter::getTotalRowCount() const
|
||||||
|
{
|
||||||
|
return _totalRowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void RowFormatter::setTotalRowCount(int count)
|
||||||
|
{
|
||||||
|
_totalRowCount = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void RowFormatter::setPrefix(const std::string& prefix) const
|
||||||
{
|
{
|
||||||
_prefix = prefix;
|
_prefix = prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void RowFormatter::setPostfix(const std::string& postfix)
|
inline void RowFormatter::setPostfix(const std::string& postfix) const
|
||||||
{
|
{
|
||||||
_postfix = postfix;
|
_postfix = postfix;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,9 @@ public:
|
|||||||
std::string& formatValues(const ValueVec& vals, std::string& formattedValues) const;
|
std::string& formatValues(const ValueVec& vals, std::string& formattedValues) const;
|
||||||
/// Formats the row values.
|
/// Formats the row values.
|
||||||
|
|
||||||
|
int rowCount() const;
|
||||||
|
/// Returns row count.
|
||||||
|
|
||||||
void setColumnWidth(std::streamsize width);
|
void setColumnWidth(std::streamsize width);
|
||||||
/// Sets the column width.
|
/// Sets the column width.
|
||||||
|
|
||||||
@@ -87,12 +90,17 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::streamsize _colWidth;
|
std::streamsize _colWidth;
|
||||||
|
mutable int _rowCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// inlines
|
/// inlines
|
||||||
///
|
///
|
||||||
|
inline int SimpleRowFormatter::rowCount() const
|
||||||
|
{
|
||||||
|
return _rowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void SimpleRowFormatter::setColumnWidth(std::streamsize columnWidth)
|
inline void SimpleRowFormatter::setColumnWidth(std::streamsize columnWidth)
|
||||||
|
|||||||
@@ -95,9 +95,9 @@ public:
|
|||||||
typedef void (*Manipulator)(Statement&);
|
typedef void (*Manipulator)(Statement&);
|
||||||
|
|
||||||
typedef ActiveResult<std::size_t> Result;
|
typedef ActiveResult<std::size_t> Result;
|
||||||
typedef SharedPtr<Result> ResultPtr;
|
typedef SharedPtr<Result> ResultPtr;
|
||||||
typedef ActiveMethod<std::size_t, void, StatementImpl> AsyncExecMethod;
|
typedef ActiveMethod<std::size_t, bool, StatementImpl> AsyncExecMethod;
|
||||||
typedef SharedPtr<AsyncExecMethod> AsyncExecMethodPtr;
|
typedef SharedPtr<AsyncExecMethod> AsyncExecMethodPtr;
|
||||||
|
|
||||||
static const int WAIT_FOREVER = -1;
|
static const int WAIT_FOREVER = -1;
|
||||||
|
|
||||||
@@ -309,17 +309,20 @@ public:
|
|||||||
const std::string& toString() const;
|
const std::string& toString() const;
|
||||||
/// Creates a string from the accumulated SQL statement.
|
/// Creates a string from the accumulated SQL statement.
|
||||||
|
|
||||||
std::size_t execute();
|
std::size_t execute(bool reset = true);
|
||||||
/// Executes the statement synchronously or asynchronously.
|
/// Executes the statement synchronously or asynchronously.
|
||||||
/// Stops when either a limit is hit or the whole statement was executed.
|
/// Stops when either a limit is hit or the whole statement was executed.
|
||||||
/// Returns the number of rows extracted from the database (for statements
|
/// Returns the number of rows extracted from the database (for statements
|
||||||
/// returning data) or number of rows affected (for all other statements).
|
/// returning data) or number of rows affected (for all other statements).
|
||||||
|
/// If reset is true (default), associated storage is reset and reused.
|
||||||
|
/// Otherwise, the results from this execution step are appended.
|
||||||
|
/// Reset argument has no meaning for unlimited statements that return all rows.
|
||||||
/// If isAsync() returns true, the statement is executed asynchronously
|
/// If isAsync() returns true, the statement is executed asynchronously
|
||||||
/// and the return value from this function is zero.
|
/// and the return value from this function is zero.
|
||||||
/// The result of execution (i.e. number of returned or affected rows) can be
|
/// The result of execution (i.e. number of returned or affected rows) can be
|
||||||
/// obtained by calling wait() on the statement at a later point in time.
|
/// obtained by calling wait() on the statement at a later point in time.
|
||||||
|
|
||||||
const Result& executeAsync();
|
const Result& executeAsync(bool reset = true);
|
||||||
/// Executes the statement asynchronously.
|
/// Executes the statement asynchronously.
|
||||||
/// Stops when either a limit is hit or the whole statement was executed.
|
/// Stops when either a limit is hit or the whole statement was executed.
|
||||||
/// Returns immediately. Calling wait() (on either the result returned from this
|
/// Returns immediately. Calling wait() (on either the result returned from this
|
||||||
@@ -373,7 +376,11 @@ public:
|
|||||||
/// Default value indicates current data set (if any).
|
/// Default value indicates current data set (if any).
|
||||||
|
|
||||||
std::size_t rowsExtracted(int dataSet = StatementImpl::USE_CURRENT_DATA_SET) const;
|
std::size_t rowsExtracted(int dataSet = StatementImpl::USE_CURRENT_DATA_SET) const;
|
||||||
/// Returns the number of rows returned for current data set.
|
/// Returns the number of rows returned for current data set during last statement
|
||||||
|
/// execution. Default value indicates current data set (if any).
|
||||||
|
|
||||||
|
std::size_t subTotalRowCount(int dataSet = StatementImpl::USE_CURRENT_DATA_SET) const;
|
||||||
|
/// Returns the number of rows extracted so far for the data set.
|
||||||
/// Default value indicates current data set (if any).
|
/// Default value indicates current data set (if any).
|
||||||
|
|
||||||
std::size_t extractionCount() const;
|
std::size_t extractionCount() const;
|
||||||
@@ -421,8 +428,11 @@ protected:
|
|||||||
const RowFormatterPtr& getRowFormatter();
|
const RowFormatterPtr& getRowFormatter();
|
||||||
/// Returns the row formatter for this statement.
|
/// Returns the row formatter for this statement.
|
||||||
|
|
||||||
|
Session session();
|
||||||
|
/// Returns the underlying session.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Result& doAsyncExec();
|
const Result& doAsyncExec(bool reset = true);
|
||||||
/// Asynchronously executes the statement.
|
/// Asynchronously executes the statement.
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -444,6 +454,14 @@ private:
|
|||||||
mutable std::string _stmtString;
|
mutable std::string _stmtString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// inlines
|
||||||
|
|
||||||
|
inline std::size_t Statement::subTotalRowCount(int dataSet) const
|
||||||
|
{
|
||||||
|
return _pImpl->subTotalRowCount(dataSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace Keywords {
|
namespace Keywords {
|
||||||
|
|
||||||
|
|||||||
@@ -144,10 +144,15 @@ public:
|
|||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
/// Create a string version of the SQL statement.
|
/// Create a string version of the SQL statement.
|
||||||
|
|
||||||
std::size_t execute();
|
std::size_t execute(const bool& reset = true);
|
||||||
/// Executes a statement. Returns the number of rows
|
/// Executes a statement. Returns the number of rows
|
||||||
/// extracted for statements returning data or number of rows
|
/// extracted for statements returning data or number of rows
|
||||||
/// affected for all other statements (insert, update, delete).
|
/// affected for all other statements (insert, update, delete).
|
||||||
|
/// If reset is true (default), the underlying bound storage is
|
||||||
|
/// reset and reused. In case of containers, this means they are
|
||||||
|
/// cleared and resized to accomodate the number of rows returned by
|
||||||
|
/// this execution step. When reset is false, data is appended to the
|
||||||
|
/// bound containers during multiple execute calls.
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
/// Resets the statement, so that we can reuse all bindings and re-execute again.
|
/// Resets the statement, so that we can reuse all bindings and re-execute again.
|
||||||
@@ -227,6 +232,10 @@ protected:
|
|||||||
/// Returns the number of rows extracted for current data set.
|
/// Returns the number of rows extracted for current data set.
|
||||||
/// Default value (USE_CURRENT_DATA_SET) indicates current data set (if any).
|
/// Default value (USE_CURRENT_DATA_SET) indicates current data set (if any).
|
||||||
|
|
||||||
|
std::size_t subTotalRowCount(int dataSet = USE_CURRENT_DATA_SET) const;
|
||||||
|
/// Returns the number of rows extracted so far for the data set.
|
||||||
|
/// Default value indicates current data set (if any).
|
||||||
|
|
||||||
const AbstractBindingVec& bindings() const;
|
const AbstractBindingVec& bindings() const;
|
||||||
/// Returns the bindings.
|
/// Returns the bindings.
|
||||||
|
|
||||||
@@ -430,9 +439,13 @@ private:
|
|||||||
void formatSQL(std::vector<Any>& arguments);
|
void formatSQL(std::vector<Any>& arguments);
|
||||||
/// Formats the SQL string by filling in placeholders with values from supplied vector.
|
/// Formats the SQL string by filling in placeholders with values from supplied vector.
|
||||||
|
|
||||||
|
void assignSubTotal(bool reset);
|
||||||
|
|
||||||
StatementImpl(const StatementImpl& stmt);
|
StatementImpl(const StatementImpl& stmt);
|
||||||
StatementImpl& operator = (const StatementImpl& stmt);
|
StatementImpl& operator = (const StatementImpl& stmt);
|
||||||
|
|
||||||
|
typedef std::vector<std::size_t> CountVec;
|
||||||
|
|
||||||
State _state;
|
State _state;
|
||||||
Limit _extrLimit;
|
Limit _extrLimit;
|
||||||
std::size_t _lowerLimit;
|
std::size_t _lowerLimit;
|
||||||
@@ -445,6 +458,7 @@ private:
|
|||||||
std::size_t _curDataSet;
|
std::size_t _curDataSet;
|
||||||
BulkType _bulkBinding;
|
BulkType _bulkBinding;
|
||||||
BulkType _bulkExtraction;
|
BulkType _bulkExtraction;
|
||||||
|
CountVec _subTotalRowCount;
|
||||||
|
|
||||||
friend class Statement;
|
friend class Statement;
|
||||||
};
|
};
|
||||||
@@ -453,6 +467,8 @@ private:
|
|||||||
//
|
//
|
||||||
// inlines
|
// inlines
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
inline void StatementImpl::addBind(AbstractBinding* pBinding)
|
inline void StatementImpl::addBind(AbstractBinding* pBinding)
|
||||||
{
|
{
|
||||||
poco_check_ptr (pBinding);
|
poco_check_ptr (pBinding);
|
||||||
|
|||||||
@@ -51,13 +51,19 @@ namespace Poco {
|
|||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
|
|
||||||
RecordSet::RecordSet(const Statement& rStatement):
|
const std::size_t RecordSet::UNKNOWN_TOTAL_ROW_COUNT = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
|
|
||||||
|
RecordSet::RecordSet(const Statement& rStatement,
|
||||||
|
RowFormatter* pRowFormatter):
|
||||||
Statement(rStatement),
|
Statement(rStatement),
|
||||||
_currentRow(0),
|
_currentRow(0),
|
||||||
_pBegin(new RowIterator(this, 0 == rowsExtracted())),
|
_pBegin(new RowIterator(this, 0 == rowsExtracted())),
|
||||||
_pEnd(new RowIterator(this, true)),
|
_pEnd(new RowIterator(this, true)),
|
||||||
_pFilter(0)
|
_pFilter(0),
|
||||||
|
_totalRowCount(UNKNOWN_TOTAL_ROW_COUNT)
|
||||||
{
|
{
|
||||||
|
if (pRowFormatter) setRowFormatter(pRowFormatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -68,7 +74,8 @@ RecordSet::RecordSet(Session& rSession,
|
|||||||
_currentRow(0),
|
_currentRow(0),
|
||||||
_pBegin(new RowIterator(this, 0 == rowsExtracted())),
|
_pBegin(new RowIterator(this, 0 == rowsExtracted())),
|
||||||
_pEnd(new RowIterator(this, true)),
|
_pEnd(new RowIterator(this, true)),
|
||||||
_pFilter(0)
|
_pFilter(0),
|
||||||
|
_totalRowCount(UNKNOWN_TOTAL_ROW_COUNT)
|
||||||
{
|
{
|
||||||
if (pRowFormatter) setRowFormatter(pRowFormatter);
|
if (pRowFormatter) setRowFormatter(pRowFormatter);
|
||||||
}
|
}
|
||||||
@@ -79,7 +86,8 @@ RecordSet::RecordSet(const RecordSet& other):
|
|||||||
_currentRow(other._currentRow),
|
_currentRow(other._currentRow),
|
||||||
_pBegin(new RowIterator(this, 0 == rowsExtracted())),
|
_pBegin(new RowIterator(this, 0 == rowsExtracted())),
|
||||||
_pEnd(new RowIterator(this, true)),
|
_pEnd(new RowIterator(this, true)),
|
||||||
_pFilter(other._pFilter)
|
_pFilter(other._pFilter),
|
||||||
|
_totalRowCount(other._totalRowCount)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +211,7 @@ Row& RecordSet::row(std::size_t pos)
|
|||||||
std::size_t RecordSet::rowCount() const
|
std::size_t RecordSet::rowCount() const
|
||||||
{
|
{
|
||||||
poco_assert (extractions().size());
|
poco_assert (extractions().size());
|
||||||
std::size_t rc = totalRowCount();
|
std::size_t rc = subTotalRowCount();
|
||||||
if (!isFiltered()) return rc;
|
if (!isFiltered()) return rc;
|
||||||
|
|
||||||
std::size_t counter = 0;
|
std::size_t counter = 0;
|
||||||
@@ -225,7 +233,7 @@ bool RecordSet::isAllowed(std::size_t row) const
|
|||||||
|
|
||||||
bool RecordSet::moveFirst()
|
bool RecordSet::moveFirst()
|
||||||
{
|
{
|
||||||
if (totalRowCount() > 0)
|
if (subTotalRowCount() > 0)
|
||||||
{
|
{
|
||||||
if (!isFiltered())
|
if (!isFiltered())
|
||||||
{
|
{
|
||||||
@@ -237,7 +245,7 @@ bool RecordSet::moveFirst()
|
|||||||
currentRow = 0;
|
currentRow = 0;
|
||||||
while (!isAllowed(currentRow))
|
while (!isAllowed(currentRow))
|
||||||
{
|
{
|
||||||
if (currentRow >= totalRowCount() - 1) return false;
|
if (currentRow >= subTotalRowCount() - 1) return false;
|
||||||
++currentRow;
|
++currentRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +261,7 @@ bool RecordSet::moveNext()
|
|||||||
std::size_t currentRow = _currentRow;
|
std::size_t currentRow = _currentRow;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (currentRow >= totalRowCount() - 1) return false;
|
if (currentRow >= subTotalRowCount() - 1) return false;
|
||||||
++currentRow;
|
++currentRow;
|
||||||
} while (isFiltered() && !isAllowed(currentRow));
|
} while (isFiltered() && !isAllowed(currentRow));
|
||||||
|
|
||||||
@@ -278,10 +286,10 @@ bool RecordSet::movePrevious()
|
|||||||
|
|
||||||
bool RecordSet::moveLast()
|
bool RecordSet::moveLast()
|
||||||
{
|
{
|
||||||
if (totalRowCount() > 0)
|
if (subTotalRowCount() > 0)
|
||||||
{
|
{
|
||||||
std::size_t currentRow = _currentRow;
|
std::size_t currentRow = _currentRow;
|
||||||
currentRow = totalRowCount() - 1;
|
currentRow = subTotalRowCount() - 1;
|
||||||
if (!isFiltered())
|
if (!isFiltered())
|
||||||
{
|
{
|
||||||
_currentRow = currentRow;
|
_currentRow = currentRow;
|
||||||
@@ -303,26 +311,21 @@ bool RecordSet::moveLast()
|
|||||||
|
|
||||||
std::ostream& RecordSet::copyValues(std::ostream& os, std::size_t offset, std::size_t length) const
|
std::ostream& RecordSet::copyValues(std::ostream& os, std::size_t offset, std::size_t length) const
|
||||||
{
|
{
|
||||||
if (length == RowIterator::POSITION_END)
|
|
||||||
{
|
|
||||||
if (0 != offset) throw RangeException("Invalid range.");
|
|
||||||
length = rowCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
RowIterator itBegin = *_pBegin + offset;
|
RowIterator itBegin = *_pBegin + offset;
|
||||||
RowIterator itEnd = itBegin + length;
|
RowIterator itEnd = (RowIterator::POSITION_END != length) ? itBegin + length : *_pEnd;
|
||||||
std::copy(itBegin, itEnd, std::ostream_iterator<Row>(os));
|
std::copy(itBegin, itEnd, std::ostream_iterator<Row>(os));
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::ostream& RecordSet::copy(std::ostream& os) const
|
std::ostream& RecordSet::copy(std::ostream& os, std::size_t offset, std::size_t length) const
|
||||||
{
|
{
|
||||||
const RowFormatter& ri = (*_pBegin)->getFormatter();
|
RowFormatter& rf = const_cast<RowFormatter&>((*_pBegin)->getFormatter());
|
||||||
os << ri.prefix();
|
rf.setTotalRowCount(getTotalRowCount());
|
||||||
|
os << rf.prefix();
|
||||||
copyNames(os);
|
copyNames(os);
|
||||||
copyValues(os);
|
copyValues(os, offset, length);
|
||||||
os << ri.postfix();
|
os << rf.postfix();
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,4 +344,10 @@ bool RecordSet::isFiltered() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RecordSet::setTotalRowCount(const std::string& sql)
|
||||||
|
{
|
||||||
|
session() << sql, into(_totalRowCount), now;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ namespace Data {
|
|||||||
|
|
||||||
RowFormatter::RowFormatter(const std::string& prefix, const std::string& postfix):
|
RowFormatter::RowFormatter(const std::string& prefix, const std::string& postfix):
|
||||||
_prefix(prefix),
|
_prefix(prefix),
|
||||||
_postfix(postfix)
|
_postfix(postfix),
|
||||||
|
_totalRowCount(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,4 +56,12 @@ RowFormatter::~RowFormatter()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RowFormatter::reset()
|
||||||
|
{
|
||||||
|
_prefix = "";
|
||||||
|
_postfix = "";
|
||||||
|
_totalRowCount = INVALID_ROW_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ void RowIterator::increment() const
|
|||||||
if (POSITION_END == _position)
|
if (POSITION_END == _position)
|
||||||
throw RangeException("End of iterator reached.");
|
throw RangeException("End of iterator reached.");
|
||||||
|
|
||||||
if (_position < _pRecordSet->totalRowCount() - 1)
|
if (_position < _pRecordSet->subTotalRowCount() - 1)
|
||||||
++_position;
|
++_position;
|
||||||
else
|
else
|
||||||
_position = POSITION_END;
|
_position = POSITION_END;
|
||||||
@@ -110,7 +110,7 @@ void RowIterator::decrement() const
|
|||||||
if (0 == _position)
|
if (0 == _position)
|
||||||
throw RangeException("Beginning of iterator reached.");
|
throw RangeException("Beginning of iterator reached.");
|
||||||
else if (POSITION_END == _position)
|
else if (POSITION_END == _position)
|
||||||
_position = _pRecordSet->totalRowCount() - 1;
|
_position = _pRecordSet->subTotalRowCount() - 1;
|
||||||
else
|
else
|
||||||
--_position;
|
--_position;
|
||||||
|
|
||||||
@@ -146,16 +146,15 @@ void RowIterator::setPosition(std::size_t pos) const
|
|||||||
std::size_t end = pos - _position;
|
std::size_t end = pos - _position;
|
||||||
for (; start < end; ++start)
|
for (; start < end; ++start)
|
||||||
{
|
{
|
||||||
if (_pRecordSet->totalRowCount() != pos) ++pos;
|
if (_pRecordSet->subTotalRowCount() != pos) ++pos;
|
||||||
else throw RangeException("Invalid position argument.");
|
else throw RangeException("Invalid position argument.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos < _pRecordSet->totalRowCount())
|
if (pos < _pRecordSet->subTotalRowCount())
|
||||||
_position = pos;
|
_position = pos;
|
||||||
else if (pos == _pRecordSet->totalRowCount())
|
else if (pos == _pRecordSet->subTotalRowCount())
|
||||||
_position = POSITION_END;
|
_position = POSITION_END;
|
||||||
else
|
else
|
||||||
throw RangeException("Invalid position argument.");
|
throw RangeException("Invalid position argument.");
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace Data {
|
|||||||
|
|
||||||
|
|
||||||
SimpleRowFormatter::SimpleRowFormatter(std::streamsize columnWidth):
|
SimpleRowFormatter::SimpleRowFormatter(std::streamsize columnWidth):
|
||||||
_colWidth(columnWidth)
|
_colWidth(columnWidth), _rowCount(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,6 +81,8 @@ void SimpleRowFormatter::swap(SimpleRowFormatter& other)
|
|||||||
|
|
||||||
std::string& SimpleRowFormatter::formatNames(const NameVecPtr pNames, std::string& formattedNames) const
|
std::string& SimpleRowFormatter::formatNames(const NameVecPtr pNames, std::string& formattedNames) const
|
||||||
{
|
{
|
||||||
|
_rowCount = 0;
|
||||||
|
|
||||||
std::ostringstream str;
|
std::ostringstream str;
|
||||||
std::string line(_colWidth * pNames->size(), '-');
|
std::string line(_colWidth * pNames->size(), '-');
|
||||||
|
|
||||||
@@ -112,10 +114,15 @@ std::string& SimpleRowFormatter::formatValues(const ValueVec& vals, std::string&
|
|||||||
}
|
}
|
||||||
else str << std::left;
|
else str << std::left;
|
||||||
|
|
||||||
str << std::setw(_colWidth) << it->convert<std::string>();
|
if (!it->isEmpty())
|
||||||
|
str << std::setw(_colWidth) << it->convert<std::string>();
|
||||||
|
else
|
||||||
|
str << std::setw(_colWidth) << "null";
|
||||||
}
|
}
|
||||||
str << std::endl;
|
str << std::endl;
|
||||||
|
|
||||||
|
++_rowCount;
|
||||||
|
|
||||||
return formattedValues = str.str();
|
return formattedValues = str.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ Statement& Statement::reset(Session& session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::size_t Statement::execute()
|
std::size_t Statement::execute(bool reset)
|
||||||
{
|
{
|
||||||
Mutex::ScopedLock lock(_mutex);
|
Mutex::ScopedLock lock(_mutex);
|
||||||
bool isDone = done();
|
bool isDone = done();
|
||||||
@@ -124,7 +124,7 @@ std::size_t Statement::execute()
|
|||||||
if (!isAsync())
|
if (!isAsync())
|
||||||
{
|
{
|
||||||
if (isDone) _pImpl->reset();
|
if (isDone) _pImpl->reset();
|
||||||
return _pImpl->execute();
|
return _pImpl->execute(reset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -136,22 +136,22 @@ std::size_t Statement::execute()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Statement::Result& Statement::executeAsync()
|
const Statement::Result& Statement::executeAsync(bool reset)
|
||||||
{
|
{
|
||||||
Mutex::ScopedLock lock(_mutex);
|
Mutex::ScopedLock lock(_mutex);
|
||||||
if (initialized() || paused() || done())
|
if (initialized() || paused() || done())
|
||||||
return doAsyncExec();
|
return doAsyncExec(reset);
|
||||||
else
|
else
|
||||||
throw InvalidAccessException("Statement still executing.");
|
throw InvalidAccessException("Statement still executing.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Statement::Result& Statement::doAsyncExec()
|
const Statement::Result& Statement::doAsyncExec(bool reset)
|
||||||
{
|
{
|
||||||
if (done()) _pImpl->reset();
|
if (done()) _pImpl->reset();
|
||||||
if (!_pAsyncExec)
|
if (!_pAsyncExec)
|
||||||
_pAsyncExec = new AsyncExecMethod(_pImpl, &StatementImpl::execute);
|
_pAsyncExec = new AsyncExecMethod(_pImpl, &StatementImpl::execute);
|
||||||
_pResult = new Result((*_pAsyncExec)());
|
_pResult = new Result((*_pAsyncExec)(reset));
|
||||||
return *_pResult;
|
return *_pResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,4 +308,11 @@ Statement& Statement::operator , (BulkFnType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Session Statement::session()
|
||||||
|
{
|
||||||
|
Poco::AutoPtr<SessionImpl> ps(&impl()->session(), true);
|
||||||
|
return Session(ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ StatementImpl::StatementImpl(SessionImpl& rSession):
|
|||||||
|
|
||||||
_extractors.resize(1);
|
_extractors.resize(1);
|
||||||
_columnsExtracted.resize(1, 0);
|
_columnsExtracted.resize(1, 0);
|
||||||
|
_subTotalRowCount.resize(1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -88,9 +89,9 @@ StatementImpl::~StatementImpl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::size_t StatementImpl::execute()
|
std::size_t StatementImpl::execute(const bool& reset)
|
||||||
{
|
{
|
||||||
resetExtraction();
|
if (reset) resetExtraction();
|
||||||
|
|
||||||
if (!_rSession.isConnected())
|
if (!_rSession.isConnected())
|
||||||
{
|
{
|
||||||
@@ -117,10 +118,32 @@ std::size_t StatementImpl::execute()
|
|||||||
if (lim < _lowerLimit)
|
if (lim < _lowerLimit)
|
||||||
throw LimitException("Did not receive enough data.");
|
throw LimitException("Did not receive enough data.");
|
||||||
|
|
||||||
|
assignSubTotal(reset);
|
||||||
|
|
||||||
return lim;
|
return lim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StatementImpl::assignSubTotal(bool reset)
|
||||||
|
{
|
||||||
|
if (_extractors.size() == _subTotalRowCount.size())
|
||||||
|
{
|
||||||
|
CountVec::iterator it = _subTotalRowCount.begin();
|
||||||
|
CountVec::iterator end = _subTotalRowCount.end();
|
||||||
|
for (int counter = 0; it != end; ++it, ++counter)
|
||||||
|
{
|
||||||
|
if (_extractors[counter].size())
|
||||||
|
{
|
||||||
|
if (reset)
|
||||||
|
*it += _extractors[counter][0]->numOfRowsHandled();
|
||||||
|
else
|
||||||
|
*it = _extractors[counter][0]->numOfRowsHandled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::size_t StatementImpl::executeWithLimit()
|
std::size_t StatementImpl::executeWithLimit()
|
||||||
{
|
{
|
||||||
poco_assert (_state != ST_DONE);
|
poco_assert (_state != ST_DONE);
|
||||||
@@ -229,13 +252,19 @@ void StatementImpl::setBulkExtraction(const Bulk& b)
|
|||||||
|
|
||||||
void StatementImpl::fixupExtraction()
|
void StatementImpl::fixupExtraction()
|
||||||
{
|
{
|
||||||
|
CountVec::iterator sIt = _subTotalRowCount.begin();
|
||||||
|
CountVec::iterator sEnd = _subTotalRowCount.end();
|
||||||
|
for (; sIt != sEnd; ++sIt) *sIt = 0;
|
||||||
|
|
||||||
|
if (_curDataSet >= _columnsExtracted.size())
|
||||||
|
{
|
||||||
|
_columnsExtracted.resize(_curDataSet + 1, 0);
|
||||||
|
_subTotalRowCount.resize(_curDataSet + 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
Poco::Data::AbstractExtractionVec::iterator it = extractions().begin();
|
Poco::Data::AbstractExtractionVec::iterator it = extractions().begin();
|
||||||
Poco::Data::AbstractExtractionVec::iterator itEnd = extractions().end();
|
Poco::Data::AbstractExtractionVec::iterator itEnd = extractions().end();
|
||||||
AbstractExtractor& ex = extractor();
|
AbstractExtractor& ex = extractor();
|
||||||
|
|
||||||
if (_curDataSet >= _columnsExtracted.size())
|
|
||||||
_columnsExtracted.resize(_curDataSet + 1, 0);
|
|
||||||
|
|
||||||
for (; it != itEnd; ++it)
|
for (; it != itEnd; ++it)
|
||||||
{
|
{
|
||||||
(*it)->setExtractor(&ex);
|
(*it)->setExtractor(&ex);
|
||||||
@@ -432,6 +461,19 @@ std::size_t StatementImpl::rowsExtracted(int dataSet) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::size_t StatementImpl::subTotalRowCount(int dataSet) const
|
||||||
|
{
|
||||||
|
if (USE_CURRENT_DATA_SET == dataSet) dataSet = _curDataSet;
|
||||||
|
if (_subTotalRowCount.size() > 0)
|
||||||
|
{
|
||||||
|
poco_assert (dataSet >= 0 && dataSet < _subTotalRowCount.size());
|
||||||
|
return _subTotalRowCount[dataSet];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void StatementImpl::formatSQL(std::vector<Any>& arguments)
|
void StatementImpl::formatSQL(std::vector<Any>& arguments)
|
||||||
{
|
{
|
||||||
std::string sql;
|
std::string sql;
|
||||||
|
|||||||
Reference in New Issue
Block a user