From 69a7f64dbfe9335b40193d20c452a416d3c00064 Mon Sep 17 00:00:00 2001 From: randomdan Date: Tue, 31 Jan 2012 00:30:49 +0000 Subject: 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 --- project2/common/aggregate.cpp | 24 ++++++++++++++++++++++ project2/common/aggregate.h | 36 +++++++++++++++++++++++++++++++++ project2/common/aggregates/distinct.cpp | 28 +++++++++++++++++++++++++ project2/common/aggregates/max.cpp | 27 +++++++++++++++++++++++++ project2/common/aggregates/min.cpp | 32 +++++++++++++++++++++++++++++ project2/common/rowView.cpp | 20 ++++++++++++++++++ project2/common/rowView.h | 5 +++++ project2/common/variables.cpp | 2 +- 8 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 project2/common/aggregate.cpp create mode 100644 project2/common/aggregate.h create mode 100644 project2/common/aggregates/distinct.cpp create mode 100644 project2/common/aggregates/max.cpp create mode 100644 project2/common/aggregates/min.cpp 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 + +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 ValueAggregateCPtr; + +class SetAggregate : public Aggregate { + public: + typedef boost::function1 UseAgg; + SetAggregate(ScriptNodePtr); + + virtual void onResultValues(const UseAgg &) const = 0; +}; +typedef boost::intrusive_ptr 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 + +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 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(&subViews)); + p->script->loader.addLoadTarget(p, Storer::into(&valueAggregates)); + p->script->loader.addLoadTarget(p, Storer::into(&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 #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 { compi(const S & s) : _s(s) { } bool operator()(const S & t) const { - return _s < t; + return t < _s; } template bool operator()(const T &) const -- cgit v1.2.3