mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-29 20:59:45 +01: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/Exception.h"
|
||||
#include <ostream>
|
||||
#include <limits>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -93,8 +94,12 @@ public:
|
||||
|
||||
using Statement::isNull;
|
||||
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.
|
||||
|
||||
explicit RecordSet(Session& rSession,
|
||||
@@ -119,9 +124,31 @@ public:
|
||||
/// for large recordsets, so it should be used judiciously.
|
||||
/// 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;
|
||||
//@ deprecated
|
||||
/// Replaced with subTotalRowCount() and getTotalRowCount().
|
||||
|
||||
std::size_t getTotalRowCount() const;
|
||||
/// Returns the total number of rows in the RecordSet.
|
||||
/// 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;
|
||||
/// Returns the number of columns in the recordset.
|
||||
@@ -340,7 +367,9 @@ public:
|
||||
/// cause RangeException to be thrown.
|
||||
/// 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.
|
||||
/// Copied strings are formatted by the current RowFormatter.
|
||||
|
||||
@@ -432,6 +461,7 @@ private:
|
||||
RowIterator* _pEnd;
|
||||
RowMap _rowMap;
|
||||
RowFilter* _pFilter;
|
||||
std::size_t _totalRowCount;
|
||||
|
||||
friend class RowIterator;
|
||||
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
|
||||
{
|
||||
return getTotalRowCount();
|
||||
}
|
||||
|
||||
|
||||
inline void RecordSet::setTotalRowCount(std::size_t totalRowCount)
|
||||
{
|
||||
_totalRowCount = totalRowCount;
|
||||
}
|
||||
|
||||
|
||||
inline std::size_t RecordSet::extractedRowCount() const
|
||||
{
|
||||
return rowsExtracted();
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
bool isEmpty() const;
|
||||
/// 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.
|
||||
|
||||
bool exists(const std::string& name) const;
|
||||
|
||||
@@ -75,7 +75,9 @@ class Data_API RowFormatter
|
||||
public:
|
||||
typedef std::vector<std::string> NameVec;
|
||||
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 = "");
|
||||
/// 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;
|
||||
/// 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;
|
||||
/// Returns prefix string;
|
||||
|
||||
const std::string& postfix() const;
|
||||
/// Returns postfix string;
|
||||
|
||||
void reset();
|
||||
/// Resets the formatter by setting prefix and postfix
|
||||
/// to empty strings and row count to INVALID_ROW_COUNT.
|
||||
|
||||
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:
|
||||
std::string _prefix;
|
||||
std::string _postfix;
|
||||
|
||||
mutable std::string _prefix;
|
||||
mutable std::string _postfix;
|
||||
int _totalRowCount;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// 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;
|
||||
}
|
||||
|
||||
|
||||
inline void RowFormatter::setPostfix(const std::string& postfix)
|
||||
inline void RowFormatter::setPostfix(const std::string& postfix) const
|
||||
{
|
||||
_postfix = postfix;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,9 @@ public:
|
||||
std::string& formatValues(const ValueVec& vals, std::string& formattedValues) const;
|
||||
/// Formats the row values.
|
||||
|
||||
int rowCount() const;
|
||||
/// Returns row count.
|
||||
|
||||
void setColumnWidth(std::streamsize width);
|
||||
/// Sets the column width.
|
||||
|
||||
@@ -87,12 +90,17 @@ public:
|
||||
|
||||
private:
|
||||
std::streamsize _colWidth;
|
||||
mutable int _rowCount;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
inline int SimpleRowFormatter::rowCount() const
|
||||
{
|
||||
return _rowCount;
|
||||
}
|
||||
|
||||
|
||||
inline void SimpleRowFormatter::setColumnWidth(std::streamsize columnWidth)
|
||||
|
||||
@@ -95,9 +95,9 @@ public:
|
||||
typedef void (*Manipulator)(Statement&);
|
||||
|
||||
typedef ActiveResult<std::size_t> Result;
|
||||
typedef SharedPtr<Result> ResultPtr;
|
||||
typedef ActiveMethod<std::size_t, void, StatementImpl> AsyncExecMethod;
|
||||
typedef SharedPtr<AsyncExecMethod> AsyncExecMethodPtr;
|
||||
typedef SharedPtr<Result> ResultPtr;
|
||||
typedef ActiveMethod<std::size_t, bool, StatementImpl> AsyncExecMethod;
|
||||
typedef SharedPtr<AsyncExecMethod> AsyncExecMethodPtr;
|
||||
|
||||
static const int WAIT_FOREVER = -1;
|
||||
|
||||
@@ -309,17 +309,20 @@ public:
|
||||
const std::string& toString() const;
|
||||
/// 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.
|
||||
/// Stops when either a limit is hit or the whole statement was executed.
|
||||
/// Returns the number of rows extracted from the database (for 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
|
||||
/// and the return value from this function is zero.
|
||||
/// 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.
|
||||
|
||||
const Result& executeAsync();
|
||||
const Result& executeAsync(bool reset = true);
|
||||
/// Executes the statement asynchronously.
|
||||
/// Stops when either a limit is hit or the whole statement was executed.
|
||||
/// Returns immediately. Calling wait() (on either the result returned from this
|
||||
@@ -373,7 +376,11 @@ public:
|
||||
/// Default value indicates current data set (if any).
|
||||
|
||||
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).
|
||||
|
||||
std::size_t extractionCount() const;
|
||||
@@ -421,8 +428,11 @@ protected:
|
||||
const RowFormatterPtr& getRowFormatter();
|
||||
/// Returns the row formatter for this statement.
|
||||
|
||||
Session session();
|
||||
/// Returns the underlying session.
|
||||
|
||||
private:
|
||||
const Result& doAsyncExec();
|
||||
const Result& doAsyncExec(bool reset = true);
|
||||
/// Asynchronously executes the statement.
|
||||
|
||||
template <typename T>
|
||||
@@ -444,6 +454,14 @@ private:
|
||||
mutable std::string _stmtString;
|
||||
};
|
||||
|
||||
//
|
||||
// inlines
|
||||
|
||||
inline std::size_t Statement::subTotalRowCount(int dataSet) const
|
||||
{
|
||||
return _pImpl->subTotalRowCount(dataSet);
|
||||
}
|
||||
|
||||
|
||||
namespace Keywords {
|
||||
|
||||
|
||||
@@ -144,10 +144,15 @@ public:
|
||||
std::string toString() const;
|
||||
/// 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
|
||||
/// extracted for statements returning data or number of rows
|
||||
/// 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();
|
||||
/// 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.
|
||||
/// 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;
|
||||
/// Returns the bindings.
|
||||
|
||||
@@ -430,9 +439,13 @@ private:
|
||||
void formatSQL(std::vector<Any>& arguments);
|
||||
/// Formats the SQL string by filling in placeholders with values from supplied vector.
|
||||
|
||||
void assignSubTotal(bool reset);
|
||||
|
||||
StatementImpl(const StatementImpl& stmt);
|
||||
StatementImpl& operator = (const StatementImpl& stmt);
|
||||
|
||||
typedef std::vector<std::size_t> CountVec;
|
||||
|
||||
State _state;
|
||||
Limit _extrLimit;
|
||||
std::size_t _lowerLimit;
|
||||
@@ -445,6 +458,7 @@ private:
|
||||
std::size_t _curDataSet;
|
||||
BulkType _bulkBinding;
|
||||
BulkType _bulkExtraction;
|
||||
CountVec _subTotalRowCount;
|
||||
|
||||
friend class Statement;
|
||||
};
|
||||
@@ -453,6 +467,8 @@ private:
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
|
||||
inline void StatementImpl::addBind(AbstractBinding* pBinding)
|
||||
{
|
||||
poco_check_ptr (pBinding);
|
||||
|
||||
Reference in New Issue
Block a user