From f64b66b7a079aa4aae8c60b4af9c7b6864d72e2c Mon Sep 17 00:00:00 2001 From: randomdan Date: Wed, 15 Dec 2010 01:54:01 +0000 Subject: 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 --- project2/fileRows.cpp | 8 +++++++ project2/fileRows.h | 1 + project2/perRowValues.cpp | 9 +++++++- project2/perRowValues.h | 5 ++++ project2/sqlMergeTask.cpp | 32 +++++++++++++++++++++++++ project2/sqlRows.cpp | 8 +++++++ project2/sqlRows.h | 1 + project2/urlRows.cpp | 9 ++++++++ project2/urlRows.h | 1 + project2/variables.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++--- project2/variables.h | 8 +++++-- project2/view.cpp | 23 ++++++++++++++---- project2/view.h | 4 ++++ project2/xmlRows.cpp | 9 ++++++++ project2/xmlRows.h | 1 + 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 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 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 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 #include #include +#include +#include +#include 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 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, + 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 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 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 def); virtual ~VariableImpl() = 0; const Glib::ustring source; @@ -27,15 +28,18 @@ class Variable { public: typedef boost::intrusive_ptr 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(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 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; -- cgit v1.2.3