summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2012-01-31 00:30:49 +0000
committerrandomdan <randomdan@localhost>2012-01-31 00:30:49 +0000
commit69a7f64dbfe9335b40193d20c452a416d3c00064 (patch)
treeb1fc1e6f522cf82f81eadd09d2a6b3068787440d
parentAdd some configurability to the Html2Text transform (diff)
downloadproject2-69a7f64dbfe9335b40193d20c452a416d3c00064.tar.bz2
project2-69a7f64dbfe9335b40193d20c452a416d3c00064.tar.xz
project2-69a7f64dbfe9335b40193d20c452a416d3c00064.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.cpp24
-rw-r--r--project2/common/aggregate.h36
-rw-r--r--project2/common/aggregates/distinct.cpp28
-rw-r--r--project2/common/aggregates/max.cpp27
-rw-r--r--project2/common/aggregates/min.cpp32
-rw-r--r--project2/common/rowView.cpp20
-rw-r--r--project2/common/rowView.h5
-rw-r--r--project2/common/variables.cpp2
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