From 31b8a0fc5616d9c2f27e49e1c706a59c90d15a45 Mon Sep 17 00:00:00 2001 From: randomdan Date: Tue, 20 Dec 2011 00:30:20 +0000 Subject: Split check and test functionality... if and check now take tests as children, adds all, any, none and not as building blocks --- project2/cgi/cgiAppEngine.h | 1 - project2/common/check.cpp | 29 +++++++++ project2/common/check.h | 25 +++++++ project2/common/checkHost.cpp | 6 +- project2/common/checkHost.h | 10 +-- project2/common/if.cpp | 118 +++++++++++++++++++++++----------- project2/common/if.h | 22 +++---- project2/common/paramChecker.cpp | 16 ----- project2/common/paramChecker.h | 23 ------- project2/common/presenter.h | 1 - project2/common/test.cpp | 7 ++ project2/common/test.h | 14 ++++ project2/common/validDateCheck.cpp | 15 +++-- project2/common/viewHost.h | 1 - project2/console/consoleAppEngine.cpp | 6 -- project2/console/consoleAppEngine.h | 1 - project2/regex/Jamfile.jam | 2 +- project2/regex/regexCheck.cpp | 25 ------- project2/regex/regexCheck.h | 19 ------ project2/regex/regexTest.cpp | 26 ++++++++ project2/regex/regexTest.h | 19 ++++++ project2/sql/Jamfile.jam | 2 +- project2/sql/sqlCheck.cpp | 101 ----------------------------- project2/sql/sqlCheck.h | 29 --------- project2/sql/sqlTest.cpp | 102 +++++++++++++++++++++++++++++ project2/sql/sqlTest.h | 29 +++++++++ 26 files changed, 359 insertions(+), 290 deletions(-) create mode 100644 project2/common/check.cpp create mode 100644 project2/common/check.h delete mode 100644 project2/common/paramChecker.cpp delete mode 100644 project2/common/paramChecker.h create mode 100644 project2/common/test.cpp create mode 100644 project2/common/test.h delete mode 100644 project2/regex/regexCheck.cpp delete mode 100644 project2/regex/regexCheck.h create mode 100644 project2/regex/regexTest.cpp create mode 100644 project2/regex/regexTest.h delete mode 100644 project2/sql/sqlCheck.cpp delete mode 100644 project2/sql/sqlCheck.h create mode 100644 project2/sql/sqlTest.cpp create mode 100644 project2/sql/sqlTest.h diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h index d4295de..e339576 100644 --- a/project2/cgi/cgiAppEngine.h +++ b/project2/cgi/cgiAppEngine.h @@ -3,7 +3,6 @@ #include "appEngine.h" #include "task.h" -#include "paramChecker.h" #include "commonObjects.h" #include "uuid.h" #include "taskHost.h" diff --git a/project2/common/check.cpp b/project2/common/check.cpp new file mode 100644 index 0000000..c284c8d --- /dev/null +++ b/project2/common/check.cpp @@ -0,0 +1,29 @@ +#include +#include "check.h" +#include "scriptLoader.h" + +DECLARE_LOADER("check", Check); +StaticMessageException(NoTestsToPerform, "No tests to perform"); + +Check::Check(ScriptNodePtr p) : + SourceObject(p), + message(p, "message", "Check failed"), + group(p, "group", "default"), + present(p, "present", "") +{ + p->script->loader.addLoadTarget(p, Storer::into(&test)); +} + +Check::~Check() +{ +} + +bool +Check::performCheck() const +{ + if (!test) { + throw NoTestsToPerform(); + } + return test->passes(); +} + diff --git a/project2/common/check.h b/project2/common/check.h new file mode 100644 index 0000000..e9f44b5 --- /dev/null +++ b/project2/common/check.h @@ -0,0 +1,25 @@ +#ifndef CHECK_H +#define CHECK_H + +#include "sourceObject.h" +#include "variables.h" +#include "test.h" + +/// Base class for Project2 compoments that perform checks +class Check : public SourceObject { + public: + Check(ScriptNodePtr p); + virtual ~Check(); + + bool performCheck() const; + + const Variable message; + const Variable group; + const Variable present; + TestPtr test; +}; +typedef boost::intrusive_ptr CheckCPtr; + +#endif + + diff --git a/project2/common/checkHost.cpp b/project2/common/checkHost.cpp index 4f2ab44..be7b572 100644 --- a/project2/common/checkHost.cpp +++ b/project2/common/checkHost.cpp @@ -6,7 +6,7 @@ CheckHost::CheckHost(ScriptReaderPtr s) : CommonObjects(s) { - s->loader.addLoadTarget(s->root(), Storer::into(¶meterChecks)); + s->loader.addLoadTarget(s->root(), Storer::into(&checks)); } CheckHost::~CheckHost() @@ -17,7 +17,7 @@ void CheckHost::runChecks() const { loadScriptComponents(); - BOOST_FOREACH(const ParamCheckers::value_type & pc, parameterChecks) { + BOOST_FOREACH(const Checks::value_type & pc, checks) { if (!pc->performCheck()) { ApplicationEngine::getCurrent()->logMessage(false, pc->group(), pc->message()); throw CheckFailure(pc); @@ -25,7 +25,7 @@ CheckHost::runChecks() const } } -CheckHost::CheckFailure::CheckFailure(ParamCheckerCPtr fc) : failedCheck(fc) +CheckHost::CheckFailure::CheckFailure(CheckCPtr fc) : failedCheck(fc) { } diff --git a/project2/common/checkHost.h b/project2/common/checkHost.h index cc32ad4..0721ac5 100644 --- a/project2/common/checkHost.h +++ b/project2/common/checkHost.h @@ -1,7 +1,7 @@ #ifndef CHECKHOST_H #define CHECKHOST_H -#include "paramChecker.h" +#include "check.h" #include "scriptStorage.h" #include #include @@ -11,17 +11,17 @@ class CheckHost : virtual public CommonObjects { public: class CheckFailure : std::exception { public: - CheckFailure(ParamCheckerCPtr); + CheckFailure(CheckCPtr); ~CheckFailure() throw(); - const ParamCheckerCPtr failedCheck; + const CheckCPtr failedCheck; }; CheckHost(ScriptReaderPtr script); ~CheckHost(); void runChecks() const; - typedef ANONORDEREDSTORAGEOF(ParamChecker) ParamCheckers; - ParamCheckers parameterChecks; + typedef ANONORDEREDSTORAGEOF(Check) Checks; + Checks checks; }; #endif diff --git a/project2/common/if.cpp b/project2/common/if.cpp index 624feef..b9db1db 100644 --- a/project2/common/if.cpp +++ b/project2/common/if.cpp @@ -7,53 +7,39 @@ #include DECLARE_LOADER("if", If); +StaticMessageException(NoTestsToPerform, "No tests to perform"); -SimpleMessageException(IfModeIsNonsense); - -IfSet::IfSet(ScriptNodePtr e) : - mode(e->value("mode", "and").as() == "or" ? Or : And) -{ - e->script->loader.addLoadTarget(e, Storer::into(&checks)); -} - -template -bool all(const Range & c, const Pred & p) +CompoundTest::CompoundTest(ScriptNodePtr s) : + SourceObject(s), + Test(s) { - return (std::find_if(c.begin(), c.end(), !p) == c.end()); -} -template -bool any(const Range & c, const Pred & p) -{ - return (std::find_if(c.begin(), c.end(), p) != c.end()); -} - -bool -IfSet::passes() const -{ - if (mode == And) { - return all(checks, boost::bind(&ParamChecker::performCheck, _1)); - } - else if (mode == Or) { - return ::any(checks, boost::bind(&ParamChecker::performCheck, _1)); - } - throw IfModeIsNonsense(getName()); + s->script->loader.addLoadTarget(s, Storer::into(&tests)); } If::If(ScriptNodePtr e) : SourceObject(e), IHaveSubTasks(e), - View(e), - IfSet(e) + View(e) { e->script->loader.addLoadTarget(e, Storer::into(&normal)); e->script->loader.addLoadTarget(e, Storer::into(&subViews)); + e->script->loader.addLoadTarget(e, Storer::into(&test)); +} + +bool +If::passes() const +{ + if (!test) { + throw NoTestsToPerform(); + } + return test->passes(); } void If::execute(const MultiRowSetPresenter * presenter) const { if (passes()) { - Logger()->messagef(LOG_DEBUG, "IfSet passed %zu checks, showing %zu views", checks.size(), subViews.size()); + Logger()->messagef(LOG_DEBUG, "Test passed; showing %zu views", subViews.size()); BOOST_FOREACH(const SubViews::value_type & sq, subViews) { sq->execute(presenter); } @@ -64,14 +50,72 @@ void If::execute() const { if (passes()) { - Logger()->message(LOG_DEBUG, "IfSet passed"); + Logger()->messagef(LOG_DEBUG, "Test passed; executing %zu tasks", normal.size()); run(normal); } } -const std::string & -If::getName() const -{ - return name; -} +class All : public CompoundTest { + public: + All(ScriptNodePtr s) : + SourceObject(s), + CompoundTest(s) { + } + bool passes() const { + if (tests.empty()) { + throw NoTestsToPerform(); + } + return (std::find_if(tests.begin(), tests.end(), !boost::bind(&Test::passes, _1)) == tests.end()); + } +}; +DECLARE_LOADER("all", All); + +class Any : public CompoundTest { + public: + Any(ScriptNodePtr s) : + SourceObject(s), + CompoundTest(s) { + } + bool passes() const { + if (tests.empty()) { + throw NoTestsToPerform(); + } + return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1)) != tests.end()); + } +}; +DECLARE_LOADER("any", Any); + +class None : public CompoundTest { + public: + None(ScriptNodePtr s) : + SourceObject(s), + CompoundTest(s) { + } + bool passes() const { + if (tests.empty()) { + throw NoTestsToPerform(); + } + return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1)) == tests.end()); + } +}; +DECLARE_LOADER("none", None); + +class Not : public Test { + public: + Not(ScriptNodePtr s) : + SourceObject(s), + Test(s) + { + s->script->loader.addLoadTarget(s, Storer::into(&test)); + } + bool passes() const { + if (!test) { + throw NoTestsToPerform(); + } + return !test->passes(); + } + private: + TestPtr test; +}; +DECLARE_LOADER("not", Not); diff --git a/project2/common/if.h b/project2/common/if.h index e27003d..bcf83cd 100644 --- a/project2/common/if.h +++ b/project2/common/if.h @@ -3,24 +3,19 @@ #include "iHaveSubTasks.h" #include "view.h" -#include "paramChecker.h" +#include "test.h" -class IfSet : public virtual IntrusivePtrBase { +class CompoundTest : public Test { public: - IfSet(ScriptNodePtr); - bool passes() const; + CompoundTest(ScriptNodePtr); - private: - virtual const std::string & getName() const = 0; - enum Mode { And, Or }; - Mode mode; - typedef ANONORDEREDSTORAGEOF(ParamChecker) ParamCheckers; protected: - ParamCheckers checks; + typedef ANONORDEREDSTORAGEOF(Test) Tests; + Tests tests; }; /// Project2 component to conditionally execute its children -class If : public IHaveSubTasks, public View, public IfSet { +class If : public IHaveSubTasks, public View { public: If(ScriptNodePtr); @@ -28,10 +23,11 @@ class If : public IHaveSubTasks, public View, public IfSet { virtual void execute() const; private: + bool passes() const; + typedef ANONSTORAGEOF(View) SubViews; SubViews subViews; - - const std::string & getName() const; + TestPtr test; }; #endif diff --git a/project2/common/paramChecker.cpp b/project2/common/paramChecker.cpp deleted file mode 100644 index 3d6b046..0000000 --- a/project2/common/paramChecker.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include "paramChecker.h" -#include "scriptLoader.h" - -ParamChecker::ParamChecker(ScriptNodePtr p) : - SourceObject(p), - message(p, "message", "Check failed"), - group(p, "group", "default"), - present(p, "present", "") -{ -} - -ParamChecker::~ParamChecker() -{ -} - diff --git a/project2/common/paramChecker.h b/project2/common/paramChecker.h deleted file mode 100644 index db3d8de..0000000 --- a/project2/common/paramChecker.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef PARAMCHECKER_H -#define PARAMCHECKER_H - -#include "sourceObject.h" -#include "variables.h" - -/// Base class for Project2 compoments that perform tests/checks -class ParamChecker : public SourceObject { - public: - ParamChecker(ScriptNodePtr p); - virtual ~ParamChecker(); - - virtual bool performCheck() const = 0; - - const Variable message; - const Variable group; - const Variable present; -}; -typedef boost::intrusive_ptr ParamCheckerCPtr; - -#endif - - diff --git a/project2/common/presenter.h b/project2/common/presenter.h index de233a3..eaba17f 100644 --- a/project2/common/presenter.h +++ b/project2/common/presenter.h @@ -6,7 +6,6 @@ #include #include #include "view.h" -#include "paramChecker.h" #include "scriptLoader.h" class NameValuePairPresenter : public virtual IntrusivePtrBase { diff --git a/project2/common/test.cpp b/project2/common/test.cpp new file mode 100644 index 0000000..f4066af --- /dev/null +++ b/project2/common/test.cpp @@ -0,0 +1,7 @@ +#include "test.h" + +Test::Test(ScriptNodePtr s) : + SourceObject(s) +{ +} + diff --git a/project2/common/test.h b/project2/common/test.h new file mode 100644 index 0000000..aa2709c --- /dev/null +++ b/project2/common/test.h @@ -0,0 +1,14 @@ +#ifndef TEST_H +#define TEST_H + +#include "sourceObject.h" +#include "scripts.h" + +class Test : public virtual SourceObject { + public: + Test(ScriptNodePtr); + virtual bool passes() const = 0; +}; +typedef boost::intrusive_ptr TestPtr; + +#endif diff --git a/project2/common/validDateCheck.cpp b/project2/common/validDateCheck.cpp index d83fa1f..be983b4 100644 --- a/project2/common/validDateCheck.cpp +++ b/project2/common/validDateCheck.cpp @@ -2,26 +2,27 @@ #include "logger.h" #include "scriptLoader.h" #include "commonObjects.h" -#include "paramChecker.h" +#include "test.h" #include "variables.h" #include "scripts.h" -class ValidDateCheck : public ParamChecker { +class ValidDateTest : public Test { public: - ValidDateCheck(ScriptNodePtr p) : - ParamChecker(p), + ValidDateTest(ScriptNodePtr p) : + SourceObject(p), + Test(p), applyTo(p, "apply-to"), format(p, "format"), warnLev(p->value("warn", true).as() ? LOG_WARNING : LOG_INFO) { } - ~ValidDateCheck() + ~ValidDateTest() { } bool - performCheck() const + passes() const { struct tm tm, ftm; memset(&tm, 0, sizeof(struct tm)); @@ -61,5 +62,5 @@ class ValidDateCheck : public ParamChecker { int warnLev; }; -DECLARE_LOADER("validdatecheck", ValidDateCheck); +DECLARE_LOADER("validdatetest", ValidDateTest); diff --git a/project2/common/viewHost.h b/project2/common/viewHost.h index 39849ec..a1468ed 100644 --- a/project2/common/viewHost.h +++ b/project2/common/viewHost.h @@ -1,7 +1,6 @@ #ifndef VIEWHOST_H #define VIEWHOST_H -#include "paramChecker.h" #include "scriptStorage.h" #include "presenter.h" #include "checkHost.h" diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp index cb8109f..7643cad 100644 --- a/project2/console/consoleAppEngine.cpp +++ b/project2/console/consoleAppEngine.cpp @@ -27,12 +27,6 @@ ConsoleApplicationEngine::~ConsoleApplicationEngine() { } -void -onCheckFailureHelper(boost::intrusive_ptr pc) -{ - throw std::runtime_error(pc->message()); -} - void ConsoleApplicationEngine::process() const { diff --git a/project2/console/consoleAppEngine.h b/project2/console/consoleAppEngine.h index 9a9ce26..a0f72e5 100644 --- a/project2/console/consoleAppEngine.h +++ b/project2/console/consoleAppEngine.h @@ -3,7 +3,6 @@ #include "appEngine.h" #include "task.h" -#include "paramChecker.h" #include "presenter.h" #include "commonObjects.h" #include "view.h" diff --git a/project2/regex/Jamfile.jam b/project2/regex/Jamfile.jam index 7bb9d16..1849b45 100644 --- a/project2/regex/Jamfile.jam +++ b/project2/regex/Jamfile.jam @@ -3,7 +3,7 @@ alias glibmm : : : : "`pkg-config --libs glibmm-2.4`" ; lib p2regex : - regexCheck.cpp regexRows.cpp + [ glob *.cpp ] : ../../libmisc glibmm diff --git a/project2/regex/regexCheck.cpp b/project2/regex/regexCheck.cpp deleted file mode 100644 index e7975bc..0000000 --- a/project2/regex/regexCheck.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "regexCheck.h" -#include "scriptLoader.h" -#include "commonObjects.h" -#include - -DECLARE_LOADER("regexcheck", RegexCheck); - -RegexCheck::RegexCheck(ScriptNodePtr p) : - ParamChecker(p), - applyTo(p, "apply-to"), - regex(p, "regex") -{ -} - -RegexCheck::~RegexCheck() -{ -} - -bool -RegexCheck::performCheck() const -{ - Glib::RefPtr reg = Glib::Regex::create(regex()); - return reg->match(applyTo()); -} - diff --git a/project2/regex/regexCheck.h b/project2/regex/regexCheck.h deleted file mode 100644 index 2ddc545..0000000 --- a/project2/regex/regexCheck.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef REGEXCHECK_H -#define REGEXCHECK_H - -#include "paramChecker.h" -#include "variables.h" - -/// Project2 component to test the value of a variable against a regular expression -class RegexCheck : public ParamChecker { - public: - RegexCheck(ScriptNodePtr p); - virtual ~RegexCheck(); - - bool performCheck() const; - - const Variable applyTo; - const Variable regex; -}; - -#endif diff --git a/project2/regex/regexTest.cpp b/project2/regex/regexTest.cpp new file mode 100644 index 0000000..93ee2f7 --- /dev/null +++ b/project2/regex/regexTest.cpp @@ -0,0 +1,26 @@ +#include "regexTest.h" +#include "scriptLoader.h" +#include "commonObjects.h" +#include + +DECLARE_LOADER("regextest", RegexTest); + +RegexTest::RegexTest(ScriptNodePtr p) : + SourceObject(p), + Test(p), + applyTo(p, "apply-to"), + regex(p, "regex") +{ +} + +RegexTest::~RegexTest() +{ +} + +bool +RegexTest::passes() const +{ + Glib::RefPtr reg = Glib::Regex::create(regex()); + return reg->match(applyTo()); +} + diff --git a/project2/regex/regexTest.h b/project2/regex/regexTest.h new file mode 100644 index 0000000..f3459bc --- /dev/null +++ b/project2/regex/regexTest.h @@ -0,0 +1,19 @@ +#ifndef REGEXTEST_H +#define REGEXTEST_H + +#include "test.h" +#include "variables.h" + +/// Project2 component to test the value of a variable against a regular expression +class RegexTest : public Test { + public: + RegexTest(ScriptNodePtr p); + virtual ~RegexTest(); + + bool passes() const; + + const Variable applyTo; + const Variable regex; +}; + +#endif diff --git a/project2/sql/Jamfile.jam b/project2/sql/Jamfile.jam index 068394f..3e63abb 100644 --- a/project2/sql/Jamfile.jam +++ b/project2/sql/Jamfile.jam @@ -32,7 +32,7 @@ cpp-pch pch : pch.hpp : ; lib p2sql : pch - sqlCheck.cpp sqlWriter.cpp sqlTask.cpp sqlMergeTask.cpp sqlRows.cpp sqlCache.cpp sqlVariableBinder.cpp tablepatch.cpp rdbmsDataSource.cpp + sqlTest.cpp sqlWriter.cpp sqlTask.cpp sqlMergeTask.cpp sqlRows.cpp sqlCache.cpp sqlVariableBinder.cpp tablepatch.cpp rdbmsDataSource.cpp sqlHandleAsVariableType.cpp ../../libdbpp//dbpp : diff --git a/project2/sql/sqlCheck.cpp b/project2/sql/sqlCheck.cpp deleted file mode 100644 index b1d369c..0000000 --- a/project2/sql/sqlCheck.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include "sqlCheck.h" -#include "scriptLoader.h" -#include "selectcommand.h" -#include "column.h" -#include "rdbmsDataSource.h" -#include "commonObjects.h" -#include "sqlVariableBinder.h" -#include -#include - -DECLARE_LOADER("sqlcheck", SqlCheck); - -class CantCompareNulls : public std::exception { }; - -SqlCheck::SqlCheck(ScriptNodePtr p) : - ParamChecker(p), - dataSource(p, "datasource"), - filter(p, "filter", ""), - testOp(p, "testOp", "=="), - testValue(p, "testValue"), - sqlCommand(p->child("sql")) -{ -} - -SqlCheck::~SqlCheck() -{ -} - -void -SqlCheck::loadComplete(const CommonObjects * co) -{ - db = co->dataSource(dataSource()); -} - -class HandleDoCompare : public DB::HandleField { - public: - HandleDoCompare(const VariableType & tV, const std::string & tO) : - retVal(false), - testValue(tV), - testOp(tO) { - } - void null() { - throw CantCompareNulls(); - } - void string(const char *c , size_t l) { - doTest(Glib::ustring(c, c + l)); - } - void integer(int64_t val) { - doTest(val); - } - void floatingpoint(double val) { - doTest(val); - } - void timestamp(const struct tm & val) { - doTest(boost::posix_time::ptime_from_tm(val)); - } - bool operator()() const { - return retVal; - } - private: - template - void doTest(const TV & val) { - TV tv = testValue; - if ((testOp == "==" || testOp == "=") && val == tv) { - retVal = true; - } - else if (testOp == "<" && val < tv) { - retVal = true; - } - else if (testOp == ">" && val > tv) { - retVal = true; - } - else if (testOp == "!=" && val != tv) { - retVal = true; - } - else if ((testOp == "<=" || testOp == "=<") && val <= tv) { - retVal = true; - } - else if ((testOp == ">=" || testOp == "=>") && val >= tv) { - retVal = true; - } - } - bool retVal; - const VariableType & testValue; - std::string testOp; -}; -bool -SqlCheck::performCheck() const -{ - boost::shared_ptr query = boost::shared_ptr( - db->getWritable().newSelectCommand(sqlCommand.getSqlFor(filter()))); - unsigned int offset = 0; - sqlCommand.bindParams(query.get(), offset); - HandleDoCompare h(testValue, testOp()); - while (query->fetch()) { - (*query)[0].apply(h); - } - return h(); -} - diff --git a/project2/sql/sqlCheck.h b/project2/sql/sqlCheck.h deleted file mode 100644 index 86492dc..0000000 --- a/project2/sql/sqlCheck.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SQLCHECK_H -#define SQLCHECK_H - -#include "paramChecker.h" -#include "sqlWriter.h" - -namespace DB { class SelectCommand; } -class RdbmsDataSource; - -/// Project2 component to check the value of a variable against an RDBMS data source -class SqlCheck : public ParamChecker { - public: - SqlCheck(ScriptNodePtr p); - virtual ~SqlCheck(); - - virtual void loadComplete(const CommonObjects *); - bool performCheck() const; - - const Variable dataSource; - const Variable filter; - const Variable testOp; - const Variable testValue; - - private: - DynamicSql::SqlCommand sqlCommand; - const RdbmsDataSource * db; -}; - -#endif diff --git a/project2/sql/sqlTest.cpp b/project2/sql/sqlTest.cpp new file mode 100644 index 0000000..3cf25b7 --- /dev/null +++ b/project2/sql/sqlTest.cpp @@ -0,0 +1,102 @@ +#include +#include "sqlTest.h" +#include "scriptLoader.h" +#include "selectcommand.h" +#include "column.h" +#include "rdbmsDataSource.h" +#include "commonObjects.h" +#include "sqlVariableBinder.h" +#include +#include + +DECLARE_LOADER("sqltest", SqlTest); + +class CantCompareNulls : public std::exception { }; + +SqlTest::SqlTest(ScriptNodePtr p) : + SourceObject(p), + Test(p), + dataSource(p, "datasource"), + filter(p, "filter", ""), + testOp(p, "testOp", "=="), + testValue(p, "testValue"), + sqlCommand(p->child("sql")) +{ +} + +SqlTest::~SqlTest() +{ +} + +void +SqlTest::loadComplete(const CommonObjects * co) +{ + db = co->dataSource(dataSource()); +} + +class HandleDoCompare : public DB::HandleField { + public: + HandleDoCompare(const VariableType & tV, const std::string & tO) : + retVal(false), + testValue(tV), + testOp(tO) { + } + void null() { + throw CantCompareNulls(); + } + void string(const char *c , size_t l) { + doTest(Glib::ustring(c, c + l)); + } + void integer(int64_t val) { + doTest(val); + } + void floatingpoint(double val) { + doTest(val); + } + void timestamp(const struct tm & val) { + doTest(boost::posix_time::ptime_from_tm(val)); + } + bool operator()() const { + return retVal; + } + private: + template + void doTest(const TV & val) { + TV tv = testValue; + if ((testOp == "==" || testOp == "=") && val == tv) { + retVal = true; + } + else if (testOp == "<" && val < tv) { + retVal = true; + } + else if (testOp == ">" && val > tv) { + retVal = true; + } + else if (testOp == "!=" && val != tv) { + retVal = true; + } + else if ((testOp == "<=" || testOp == "=<") && val <= tv) { + retVal = true; + } + else if ((testOp == ">=" || testOp == "=>") && val >= tv) { + retVal = true; + } + } + bool retVal; + const VariableType & testValue; + std::string testOp; +}; +bool +SqlTest::passes() const +{ + boost::shared_ptr query = boost::shared_ptr( + db->getWritable().newSelectCommand(sqlCommand.getSqlFor(filter()))); + unsigned int offset = 0; + sqlCommand.bindParams(query.get(), offset); + HandleDoCompare h(testValue, testOp()); + while (query->fetch()) { + (*query)[0].apply(h); + } + return h(); +} + diff --git a/project2/sql/sqlTest.h b/project2/sql/sqlTest.h new file mode 100644 index 0000000..f722424 --- /dev/null +++ b/project2/sql/sqlTest.h @@ -0,0 +1,29 @@ +#ifndef SQLTEST_H +#define SQLTEST_H + +#include "test.h" +#include "sqlWriter.h" + +namespace DB { class SelectCommand; } +class RdbmsDataSource; + +/// Project2 component to test the value of a variable against an RDBMS data source +class SqlTest : public Test { + public: + SqlTest(ScriptNodePtr p); + virtual ~SqlTest(); + + virtual void loadComplete(const CommonObjects *); + bool passes() const; + + const Variable dataSource; + const Variable filter; + const Variable testOp; + const Variable testValue; + + private: + DynamicSql::SqlCommand sqlCommand; + const RdbmsDataSource * db; +}; + +#endif -- cgit v1.2.3