diff options
author | randomdan <randomdan@localhost> | 2012-01-31 00:30:49 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2012-01-31 00:30:49 +0000 |
commit | 0b014943efe1cbddf7312bf00758e1d657aaa745 (patch) | |
tree | b1fc1e6f522cf82f81eadd09d2a6b3068787440d | |
parent | Add some configurability to the Html2Text transform (diff) | |
download | project2-0b014943efe1cbddf7312bf00758e1d657aaa745.tar.bz2 project2-0b014943efe1cbddf7312bf00758e1d657aaa745.tar.xz project2-0b014943efe1cbddf7312bf00758e1d657aaa745.zip |
Add support for aggregates in row views
Add a few aggregates implementations (min, max, distinct)
Use distinct to get the GB homepage in a single DB trip
Fix lessthan operation on variable types to be the right way round as it now matters
-rw-r--r-- | project2/common/aggregate.cpp | 24 | ||||
-rw-r--r-- | project2/common/aggregate.h | 36 | ||||
-rw-r--r-- | project2/common/aggregates/distinct.cpp | 28 | ||||
-rw-r--r-- | project2/common/aggregates/max.cpp | 27 | ||||
-rw-r--r-- | project2/common/aggregates/min.cpp | 32 | ||||
-rw-r--r-- | project2/common/rowView.cpp | 20 | ||||
-rw-r--r-- | project2/common/rowView.h | 5 | ||||
-rw-r--r-- | project2/common/variables.cpp | 2 |
8 files changed, 173 insertions, 1 deletions
diff --git a/project2/common/aggregate.cpp b/project2/common/aggregate.cpp new file mode 100644 index 0000000..1bb453b --- /dev/null +++ b/project2/common/aggregate.cpp @@ -0,0 +1,24 @@ +#include "aggregate.h" + +Aggregate::Aggregate(ScriptNodePtr s) : + SourceObject(s), + value(s, "value") +{ +} + +ValueAggregate::ValueAggregate(ScriptNodePtr s) : + Aggregate(s) +{ +} + +SetAggregate::SetAggregate(ScriptNodePtr s) : + Aggregate(s) +{ +} + +void +Aggregate::pushValue() const +{ + pushValue(value()); +} + diff --git a/project2/common/aggregate.h b/project2/common/aggregate.h new file mode 100644 index 0000000..18ad6a5 --- /dev/null +++ b/project2/common/aggregate.h @@ -0,0 +1,36 @@ +#ifndef AGGREGATE_H +#define AGGREGATE_H + +#include "scripts.h" +#include <boost/function.hpp> + +class Aggregate : public SourceObject { + public: + Aggregate(ScriptNodePtr); + + virtual void reset() const = 0; + void pushValue() const; + protected: + virtual void pushValue(const VariableType &) const = 0; + private: + Variable value; +}; + +class ValueAggregate : public Aggregate { + public: + ValueAggregate(ScriptNodePtr); + + virtual VariableType resultValue() const = 0; +}; +typedef boost::intrusive_ptr<const ValueAggregate> ValueAggregateCPtr; + +class SetAggregate : public Aggregate { + public: + typedef boost::function1<void, VariableType> UseAgg; + SetAggregate(ScriptNodePtr); + + virtual void onResultValues(const UseAgg &) const = 0; +}; +typedef boost::intrusive_ptr<const SetAggregate> SetAggregateCPtr; + +#endif diff --git a/project2/common/aggregates/distinct.cpp b/project2/common/aggregates/distinct.cpp new file mode 100644 index 0000000..85e69c2 --- /dev/null +++ b/project2/common/aggregates/distinct.cpp @@ -0,0 +1,28 @@ +#include "../aggregate.h" +#include <boost/foreach.hpp> + +class Distinct : public SetAggregate { + public: + Distinct(ScriptNodePtr s) : + SetAggregate(s) + { + } + void reset() const + { + result.clear(); + } + void pushValue(const VariableType & v) const + { + result.insert(v); + } + void onResultValues(const SetAggregate::UseAgg & u) const + { + BOOST_FOREACH(const VariableType & v, result) { + u(v); + } + } + private: + mutable std::set<VariableType> result; +}; + +DECLARE_LOADER("distinct", Distinct); diff --git a/project2/common/aggregates/max.cpp b/project2/common/aggregates/max.cpp new file mode 100644 index 0000000..a6e528a --- /dev/null +++ b/project2/common/aggregates/max.cpp @@ -0,0 +1,27 @@ +#include "../aggregate.h" + +class Max : public ValueAggregate { + public: + Max(ScriptNodePtr s) : ValueAggregate(s) { } + + void reset() const + { + result = VariableType(); + } + void pushValue(const VariableType & v) const + { + if (result < v) { + result = v; + } + } + VariableType resultValue() const + { + return result; + } + private: + mutable VariableType result; +}; + +DECLARE_LOADER("max", Max); + + diff --git a/project2/common/aggregates/min.cpp b/project2/common/aggregates/min.cpp new file mode 100644 index 0000000..14c63ae --- /dev/null +++ b/project2/common/aggregates/min.cpp @@ -0,0 +1,32 @@ +#include "../aggregate.h" + +class Min : public ValueAggregate { + public: + Min(ScriptNodePtr s) : + ValueAggregate(s), + first(true) + { + } + void reset() const + { + result = VariableType(); + first = true; + } + void pushValue(const VariableType & v) const + { + if (first || v < result) { + result = v; + } + first = false; + } + VariableType resultValue() const + { + return result; + } + private: + mutable VariableType result; + mutable bool first; +}; + +DECLARE_LOADER("min", Min); + diff --git a/project2/common/rowView.cpp b/project2/common/rowView.cpp index 0f25a30..749651e 100644 --- a/project2/common/rowView.cpp +++ b/project2/common/rowView.cpp @@ -20,6 +20,8 @@ RowView::RowView(ScriptNodePtr p) : viewColumns.insert(Columns::value_type(node->get_name(), Variable(node))); } p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&subViews)); + p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&valueAggregates)); + p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&setAggregates)); } RowView::~RowView() @@ -46,6 +48,12 @@ RowView::rowReady(const RowState * rs) const } executeChildren(); presenter->finishRow(); + BOOST_FOREACH(SetAggregateCPtr s, setAggregates) { + s->pushValue(); + } + BOOST_FOREACH(ValueAggregateCPtr a, valueAggregates) { + a->pushValue(); + } } void @@ -53,8 +61,20 @@ RowView::execute(const MultiRowSetPresenter * p) const { presenter = p; presenter->addNewRowSet(rootName()); + ScopeObject pres(boost::bind(&MultiRowSetPresenter::finishRowSet, p)); RowProcessor::execute(); + + BOOST_FOREACH(SetAggregateCPtr s, setAggregates) { + presenter->addNewRowSet(s->name); + ScopeObject pres(boost::bind(&MultiRowSetPresenter::finishRowSet, p)); + s->onResultValues(boost::bind(&MultiRowSetPresenter::addNamedValue, p, "value", _1)); + s->reset(); + } + BOOST_FOREACH(ValueAggregateCPtr a, valueAggregates) { + presenter->addNamedValue(a->name, a->resultValue()); + a->reset(); + } } void diff --git a/project2/common/rowView.h b/project2/common/rowView.h index 4b90884..40ec8a9 100644 --- a/project2/common/rowView.h +++ b/project2/common/rowView.h @@ -4,6 +4,7 @@ #include <boost/intrusive_ptr.hpp> #include "rowProcessor.h" #include "view.h" +#include "aggregate.h" /// Project2 component to create output based on a records in a row set class RowView : public View, public RowProcessor { @@ -25,6 +26,10 @@ class RowView : public View, public RowProcessor { void executeChildren() const; typedef ANONSTORAGEOF(View) SubViews; SubViews subViews; + typedef ANONSTORAGEOF(ValueAggregate) ValueAggregates; + ValueAggregates valueAggregates; + typedef ANONSTORAGEOF(SetAggregate) SetAggregates; + SetAggregates setAggregates; mutable const MultiRowSetPresenter * presenter; }; diff --git a/project2/common/variables.cpp b/project2/common/variables.cpp index 8b4ce38..de0690b 100644 --- a/project2/common/variables.cpp +++ b/project2/common/variables.cpp @@ -165,7 +165,7 @@ class compi : public boost::static_visitor<bool> { compi(const S & s) : _s(s) { } bool operator()(const S & t) const { - return _s < t; + return t < _s; } template <class T> bool operator()(const T &) const |