summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2010-12-15 01:54:01 +0000
committerrandomdan <randomdan@localhost>2010-12-15 01:54:01 +0000
commitf64b66b7a079aa4aae8c60b4af9c7b6864d72e2c (patch)
tree4aa35e366abc5b03110fbd6af6a17a012faf35da
parentAll new fangled iterators, views, row engines, exceptions, the list goes on (diff)
downloadproject2-f64b66b7a079aa4aae8c60b4af9c7b6864d72e2c.tar.bz2
project2-f64b66b7a079aa4aae8c60b4af9c7b6864d72e2c.tar.xz
project2-f64b66b7a079aa4aae8c60b4af9c7b6864d72e2c.zip
Add support for non-default Sql merge inserter
and row numbers in row sets and functional row properties in variables and custom column sub/super sets in views and isNull by column name Fix somee constnesses
-rw-r--r--project2/fileRows.cpp8
-rw-r--r--project2/fileRows.h1
-rw-r--r--project2/perRowValues.cpp9
-rw-r--r--project2/perRowValues.h5
-rw-r--r--project2/sqlMergeTask.cpp32
-rw-r--r--project2/sqlRows.cpp8
-rw-r--r--project2/sqlRows.h1
-rw-r--r--project2/urlRows.cpp9
-rw-r--r--project2/urlRows.h1
-rw-r--r--project2/variables.cpp59
-rw-r--r--project2/variables.h8
-rw-r--r--project2/view.cpp23
-rw-r--r--project2/view.h4
-rw-r--r--project2/xmlRows.cpp9
-rw-r--r--project2/xmlRows.h1
15 files changed, 168 insertions, 10 deletions
diff --git a/project2/fileRows.cpp b/project2/fileRows.cpp
index 2f4d6cf..3a16ed6 100644
--- a/project2/fileRows.cpp
+++ b/project2/fileRows.cpp
@@ -51,6 +51,7 @@ _FileRows::getColumnName(unsigned int col) const
void
_FileRows::execute(const RowProcessor * rp) const
{
+ rowNum = 0;
FileStarChannel c(doOpen());
c.set_encoding(encoding);
c.set_line_term(newline);
@@ -105,6 +106,7 @@ _FileRows::execute(const RowProcessor * rp) const
curCol++;
}
rp->rowReady();
+ rowNum += 1;
}
values.clear();
}
@@ -122,6 +124,12 @@ _FileRows::isNull(unsigned int col) const
return false;
}
+bool
+_FileRows::isNull(const Glib::ustring & col) const
+{
+ return false;
+}
+
const Glib::ustring &
_FileRows::getCurrentValue(const Glib::ustring & id) const
{
diff --git a/project2/fileRows.h b/project2/fileRows.h
index 60916ac..899205c 100644
--- a/project2/fileRows.h
+++ b/project2/fileRows.h
@@ -24,6 +24,7 @@ class _FileRows : public PerRowValues {
const Glib::ustring & getCurrentValue(const Glib::ustring & id) const;
const Glib::ustring & getCurrentValue(unsigned int col) const;
bool isNull(unsigned int col) const;
+ bool isNull(const Glib::ustring & id) const;
typedef std::set<gunichar> CharSet;
const Variable path;
diff --git a/project2/perRowValues.cpp b/project2/perRowValues.cpp
index 82b46bc..4666735 100644
--- a/project2/perRowValues.cpp
+++ b/project2/perRowValues.cpp
@@ -7,7 +7,8 @@
PerRowValues::RowValuesStack PerRowValues::stack;
PerRowValues::PerRowValues(const xmlpp::Element * p) :
- _SourceObject(p)
+ _SourceObject(p),
+ rowNum(-1)
{
}
@@ -51,6 +52,12 @@ PerRowValues::rowChanged() const
}
}
+unsigned int
+PerRowValues::getRowNum() const
+{
+ return rowNum;
+}
+
RowUser::RowUser()
{
}
diff --git a/project2/perRowValues.h b/project2/perRowValues.h
index abd1507..52b6024 100644
--- a/project2/perRowValues.h
+++ b/project2/perRowValues.h
@@ -48,6 +48,8 @@ class PerRowValues : public virtual _SourceObject {
virtual const Glib::ustring & getCurrentValue(const Glib::ustring & id) const = 0;
virtual const Glib::ustring & getCurrentValue(unsigned int col) const = 0;
virtual bool isNull(unsigned int col) const = 0;
+ virtual bool isNull(const Glib::ustring & id) const = 0;
+ unsigned int getRowNum() const;
virtual void execute(const RowProcessor *) const = 0;
void use(const RowUser * r) const;
void finish(const RowUser * r) const;
@@ -57,6 +59,9 @@ class PerRowValues : public virtual _SourceObject {
static void endRow(const PerRowValues * r);
void rowChanged() const;
+ protected:
+ mutable unsigned int rowNum;
+
private:
static RowValuesStack stack;
mutable std::set<const RowUser *> rowUsers;
diff --git a/project2/sqlMergeTask.cpp b/project2/sqlMergeTask.cpp
index 279fa05..360c98b 100644
--- a/project2/sqlMergeTask.cpp
+++ b/project2/sqlMergeTask.cpp
@@ -10,7 +10,30 @@
bool _SqlMergeTask::defaultUseTempTable = true;
static void attach(Iterate i, ModifyCommand * insert);
+class _SqlMergeInsert;
+typedef boost::intrusive_ptr<_SqlMergeInsert> SqlMergeInsert;
+class _SqlMergeInsert : public IHaveParameters, public virtual _SourceObject, public _Task {
+ public:
+ _SqlMergeInsert(const xmlpp::Element * p) :
+ _SourceObject(p),
+ IHaveParameters(p),
+ _Task(p) {
+ }
+ void loadComplete(const CommonObjects*) {
+ }
+ void execute() const {
+ unsigned int col = 0;
+ BOOST_FOREACH(const Parameters::value_type & v, parameters) {
+ insert->bindParamS(col++, v.second->value);
+ }
+ }
+ private:
+ friend void attach(SqlMergeInsert i, ModifyCommand * insert);
+ ModifyCommand * insert;
+};
+
ElementLoaderImpl<_SqlMergeTask> sqlmergeLoader("sqlmerge");
+ElementLoaderImpl<_SqlMergeInsert> sqlmergeinsertLoader("sqlmergeinsert");
// Conversion logic
_SqlMergeTask::_SqlMergeTask(const xmlpp::Element * p) :
@@ -232,6 +255,14 @@ class _Populate : public _NoOutputExecute {
};
typedef boost::intrusive_ptr<_Populate> Populate;
+void
+attach(SqlMergeInsert i, ModifyCommand * insert)
+{
+ if (i) {
+ i->insert = insert;
+ }
+}
+
static void
attach(Iterate i, ModifyCommand * insert)
{
@@ -244,6 +275,7 @@ attach(Iterate i, ModifyCommand * insert)
else {
BOOST_FOREACH(const NoOutputExecutes::value_type & n, i->subNOEs) {
attach(boost::dynamic_pointer_cast<_Iterate>(n.second), insert);
+ attach(boost::dynamic_pointer_cast<_SqlMergeInsert>(n.second), insert);
}
}
}
diff --git a/project2/sqlRows.cpp b/project2/sqlRows.cpp
index 9244a9c..1924207 100644
--- a/project2/sqlRows.cpp
+++ b/project2/sqlRows.cpp
@@ -57,6 +57,12 @@ _SqlRows::isNull(unsigned int col) const
return (*query)[col].isNull();
}
+bool
+_SqlRows::isNull(const Glib::ustring & col) const
+{
+ return (*query)[col].isNull();
+}
+
unsigned int
_SqlRows::columnCount() const
{
@@ -72,6 +78,7 @@ _SqlRows::getColumnName(unsigned int col) const
void
_SqlRows::execute(const RowProcessor * rp) const
{
+ rowNum = 0;
unsigned int offset = 0;
Glib::ustring sql;
sqlCommand.writeSql(sql);
@@ -79,6 +86,7 @@ _SqlRows::execute(const RowProcessor * rp) const
sqlCommand.bindParams(rp, query, offset);
while (query->fetch()) {
rp->rowReady();
+ rowNum += 1;
}
delete query;
}
diff --git a/project2/sqlRows.h b/project2/sqlRows.h
index b983743..a00c8ce 100644
--- a/project2/sqlRows.h
+++ b/project2/sqlRows.h
@@ -23,6 +23,7 @@ class _SqlRows : public PerRowValues {
const Glib::ustring & getCurrentValue(const Glib::ustring & id) const;
const Glib::ustring & getCurrentValue(unsigned int col) const;
bool isNull(unsigned int col) const;
+ bool isNull(const Glib::ustring & id) const;
const std::string dataSource;
diff --git a/project2/urlRows.cpp b/project2/urlRows.cpp
index 8381d68..94ee05e 100644
--- a/project2/urlRows.cpp
+++ b/project2/urlRows.cpp
@@ -67,6 +67,12 @@ _UrlRows::isNull(unsigned int col) const
return false;
}
+bool
+_UrlRows::isNull(const Glib::ustring & col) const
+{
+ return false;
+}
+
const Glib::ustring &
_UrlRows::getCurrentValue(const Glib::ustring & id) const
{
@@ -109,6 +115,7 @@ _UrlRows::handleData(const RowProcessor * rp, const char * bytes, size_t bytesLe
values.push_back(ValPtr(new Glib::ustring()));
}
rp->rowReady();
+ rowNum += 1;
}
else {
mkCols = false;
@@ -167,6 +174,7 @@ _UrlRows::addColumn(const Glib::ustring & rawtok) const
void
_UrlRows::execute(const RowProcessor * rp) const
{
+ rowNum = 0;
CurlHandle::Ptr c = new CurlHandle();
c->setopt(CURLOPT_URL, url.c_str());
//c->setopt(CURLOPT_PROXY, proxy.c_str());
@@ -194,6 +202,7 @@ _UrlRows::execute(const RowProcessor * rp) const
values.push_back(ValPtr(new Glib::ustring()));
}
rp->rowReady();
+ rowNum += 1;
values.clear();
}
values.clear();
diff --git a/project2/urlRows.h b/project2/urlRows.h
index 08acffc..83c11ce 100644
--- a/project2/urlRows.h
+++ b/project2/urlRows.h
@@ -20,6 +20,7 @@ class _UrlRows : public PerRowValues {
const Glib::ustring & getCurrentValue(const Glib::ustring & id) const;
const Glib::ustring & getCurrentValue(unsigned int col) const;
bool isNull(unsigned int col) const;
+ bool isNull(const Glib::ustring & id) const;
typedef std::set<gunichar> CharSet;
const Glib::ustring url;
diff --git a/project2/variables.cpp b/project2/variables.cpp
index 09ea36e..c6a65f1 100644
--- a/project2/variables.cpp
+++ b/project2/variables.cpp
@@ -8,6 +8,9 @@
#include <boost/tokenizer.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string/predicate.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
class VariableLiteral : public VariableImpl {
public:
@@ -19,6 +22,7 @@ class VariableLiteral : public VariableImpl {
class VariableImplDyn : public VariableImpl {
public:
VariableImplDyn(const Glib::ustring & src) : VariableImpl(src), cacheValid(false) { }
+ VariableImplDyn(const Glib::ustring & src, boost::optional<Glib::ustring> def) : VariableImpl(src, def), cacheValid(false) { }
virtual const Glib::ustring & value() const = 0;
protected:
@@ -94,6 +98,15 @@ class VariableParent : public VariableImplDyn, public RowUser {
depth(src.length() - source.length()),
dep(d)
{
+ bind();
+ }
+ VariableParent(const Glib::ustring & name, unsigned int d) :
+ VariableImplDyn(name, NULL),
+ row(NULL),
+ depth(d),
+ dep(NULL)
+ {
+ bind();
}
~VariableParent()
{
@@ -120,7 +133,7 @@ class VariableParent : public VariableImplDyn, public RowUser {
row->use(dep);
}
}
- cache = row->getCurrentValue(name);
+ getValue(cache, row);
}
catch (PerRowValues::ParentOutOfRange) {
if (!defaultValue) {
@@ -143,9 +156,31 @@ class VariableParent : public VariableImplDyn, public RowUser {
cacheValid = false;
}
protected:
+ static void assignHelper(Glib::ustring & dest, const Glib::ustring & src) {
+ dest = src;
+ }
+ void bind()
+ {
+ if (name[0] == '!') {
+ if (name == "!rownum") {
+ getValue = boost::bind(&assignHelper, _1,
+ boost::bind(&boost::lexical_cast<Glib::ustring, unsigned int>,
+ boost::bind(&PerRowValues::getRowNum, _2)));
+ }
+ else {
+ throw PerRowValues::FieldDoesNotExist();
+ }
+ }
+ else {
+ typedef const Glib::ustring & (PerRowValues::*gCV)(const Glib::ustring &) const;
+ getValue = boost::bind(&assignHelper, _1,
+ boost::bind((gCV)&PerRowValues::getCurrentValue, _2, name));
+ }
+ }
mutable const PerRowValues * row;
const size_t depth;
const RowUser * dep;
+ boost::function2<void, Glib::ustring &, const PerRowValues *> getValue;
};
class VariableParse : public VariableImplDyn, public RowUser {
@@ -190,16 +225,21 @@ Variable::Variable(const Glib::ustring & s) :
{
}
-Variable::Variable(xmlpp::Attribute * a) :
+Variable::Variable(const xmlpp::Attribute * a) :
var(create(a->get_value()))
{
}
-Variable::Variable(xmlpp::Element * e) :
+Variable::Variable(const xmlpp::Element * e) :
var(create(e->get_child_text()->get_content()))
{
}
+Variable::Variable(VariableImpl * v) :
+ var(v)
+{
+}
+
Variable::VariableImplPtr
Variable::create(const Glib::ustring & s, RowUser * dep)
{
@@ -224,6 +264,19 @@ Variable::create(const Glib::ustring & s, RowUser * dep)
}
}
+Variable
+Variable::makeParent(const Glib::ustring & n, unsigned int d)
+{
+ return Variable(new VariableParent(n, d));
+}
+
+VariableImpl::VariableImpl(const Glib::ustring & src, boost::optional<Glib::ustring> def) :
+ source(src),
+ name(src),
+ defaultValue(def)
+{
+}
+
VariableImpl::VariableImpl(const Glib::ustring & src) :
source(src)
{
diff --git a/project2/variables.h b/project2/variables.h
index c927ae6..c728284 100644
--- a/project2/variables.h
+++ b/project2/variables.h
@@ -16,6 +16,7 @@ class VariableImpl : public virtual IntrusivePtrBase {
protected:
VariableImpl(const Glib::ustring & src);
+ VariableImpl(const Glib::ustring & src, boost::optional<Glib::ustring> def);
virtual ~VariableImpl() = 0;
const Glib::ustring source;
@@ -27,15 +28,18 @@ class Variable {
public:
typedef boost::intrusive_ptr<VariableImpl> VariableImplPtr;
- Variable(xmlpp::Attribute *);
- Variable(xmlpp::Element *);
+ Variable(const xmlpp::Attribute *);
+ Variable(const xmlpp::Element *);
Variable(const Glib::ustring & s);
+ static Variable makeParent(const Glib::ustring & name, unsigned int depth);
+
operator const Glib::ustring & () const { return var->value(); }
const Glib::ustring & operator()() const { return var->value(); }
const Glib::ustring * operator->() const { return &var->value(); }
private:
+ Variable(VariableImpl *);
friend class VariableParse;
static VariableImplPtr create(const Glib::ustring & s, RowUser * dep = NULL);
VariableImplPtr var;
diff --git a/project2/view.cpp b/project2/view.cpp
index 06eb6cc..d32b275 100644
--- a/project2/view.cpp
+++ b/project2/view.cpp
@@ -21,6 +21,12 @@ _RowView::_RowView(const xmlpp::Element * p) :
rootName(p->get_attribute_value("rootname")),
recordName(p->get_attribute_value("recordname"))
{
+ BOOST_FOREACH(xmlpp::Node * node, p->find("columns/column")) {
+ const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node);
+ if (elem) {
+ viewColumns.insert(Columns::value_type(elem->get_attribute_value("name"), Variable::makeParent(elem->get_child_text()->get_content(), 0)));
+ }
+ }
LoaderBase loader("http://project2.randomdan.homeip.net", true);
loader.supportedStorers.insert(Storer::into(&subViews));
loader.collectAll(p, true);
@@ -40,10 +46,19 @@ void
_RowView::rowReady() const
{
presenter->pushSub(recordName);
- unsigned int cols = source->columnCount();
- for (unsigned int c = 0; c < cols; c += 1) {
- if (!source->isNull(c)) {
- presenter->addField(source->getColumnName(c), source->getCurrentValue(c));
+ if (viewColumns.empty()) {
+ unsigned int cols = source->columnCount();
+ for (unsigned int c = 0; c < cols; c += 1) {
+ if (!source->isNull(c)) {
+ presenter->addField(source->getColumnName(c), source->getCurrentValue(c));
+ }
+ }
+ }
+ else {
+ BOOST_FOREACH(const Columns::value_type & col, viewColumns) {
+ if (!source->isNull(col.first)) {
+ presenter->addField(col.first, col.second);
+ }
}
}
executeChildren();
diff --git a/project2/view.h b/project2/view.h
index 332e13f..081cf13 100644
--- a/project2/view.h
+++ b/project2/view.h
@@ -7,6 +7,7 @@
#include "sourceObject.h"
#include "xmlObjectLoader.h"
#include "perRowValues.h"
+#include "variables.h"
class Presenter;
class _View;
@@ -34,6 +35,9 @@ class _RowView : public _View, public RowProcessor {
const Glib::ustring recordName;
protected:
+ typedef std::map<Glib::ustring, Variable> Columns;
+ Columns viewColumns;
+
void executeChildren() const;
Views subViews;
mutable const Presenter * presenter;
diff --git a/project2/xmlRows.cpp b/project2/xmlRows.cpp
index 63a14cc..bfccca1 100644
--- a/project2/xmlRows.cpp
+++ b/project2/xmlRows.cpp
@@ -86,6 +86,12 @@ _XmlRows::isNull(unsigned int col) const
return (values.find(fieldNames[col]) == values.end());
}
+bool
+_XmlRows::isNull(const Glib::ustring & col) const
+{
+ return (values.find(col) == values.end());
+}
+
unsigned int
_XmlRows::columnCount() const
{
@@ -110,6 +116,7 @@ store(const _XmlRows::Path & position, _XmlRows::Values & values, const _XmlRows
void
_XmlRows::execute(const RowProcessor * rp) const
{
+ rowNum = 0;
xmlTextReaderPtr reader = xmlReaderForFile(filename.c_str(), NULL, 0);
if (reader == NULL) {
throw std::runtime_error("Failed to open file");
@@ -136,6 +143,7 @@ _XmlRows::execute(const RowProcessor * rp) const
if (empty) {
if (position == trigger) {
rp->rowReady();
+ rowNum += 1;
}
if (position == root) {
values.clear();
@@ -153,6 +161,7 @@ _XmlRows::execute(const RowProcessor * rp) const
if (enableCapture) {
if (position == trigger) {
rp->rowReady();
+ rowNum += 1;
}
if (position == root) {
values.clear();
diff --git a/project2/xmlRows.h b/project2/xmlRows.h
index 05c127d..6e671de 100644
--- a/project2/xmlRows.h
+++ b/project2/xmlRows.h
@@ -23,6 +23,7 @@ class _XmlRows : public PerRowValues {
const Glib::ustring & getCurrentValue(const Glib::ustring & id) const;
const Glib::ustring & getCurrentValue(unsigned int col) const;
bool isNull(unsigned int col) const;
+ bool isNull(const Glib::ustring & id) const;
const Glib::ustring recordRoot;
const Glib::ustring recordTrigger;