diff --git a/arangod/Aql/ExecutionBlock.cpp b/arangod/Aql/ExecutionBlock.cpp index 393038d7b3..12a707310e 100644 --- a/arangod/Aql/ExecutionBlock.cpp +++ b/arangod/Aql/ExecutionBlock.cpp @@ -41,6 +41,27 @@ int ExecutionBlock::bind (std::map* params) { return TRI_ERROR_NO_ERROR; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief functionality to walk an execution plan recursively +//////////////////////////////////////////////////////////////////////////////// + +void ExecutionBlock::walk (WalkerWorker& worker) { + worker.before(this); + for (auto it = _dependencies.begin(); + it != _dependencies.end(); + ++it) { + (*it)->walk(worker); + } + if (_exePlan->getType() == ExecutionPlan::SUBQUERY) { + // auto p = static_cast(this); + worker.enterSubquery(this, nullptr); // p->_subquery + // p->_subquery->walk(worker); + worker.leaveSubquery(this, nullptr); // p->_subquery + } + worker.after(this); +} + + // ----------------------------------------------------------------------------- // --SECTION-- factory for instanciation of plans // ----------------------------------------------------------------------------- diff --git a/arangod/Aql/ExecutionBlock.h b/arangod/Aql/ExecutionBlock.h index 9167cad8f4..5999d14596 100644 --- a/arangod/Aql/ExecutionBlock.h +++ b/arangod/Aql/ExecutionBlock.h @@ -95,6 +95,24 @@ namespace triagens { } } +//////////////////////////////////////////////////////////////////////////////// +/// @brief functionality to walk an execution plan recursively +//////////////////////////////////////////////////////////////////////////////// + + class WalkerWorker { + public: + WalkerWorker () {}; + virtual ~WalkerWorker () {}; + virtual void before (ExecutionBlock* eb) {}; + virtual void after (ExecutionBlock* eb) {}; + virtual void enterSubquery (ExecutionBlock* super, + ExecutionBlock* sub) {}; + virtual void leaveSubquery (ExecutionBlock* super, + ExecutionBlock* sub) {}; + }; + + void walk (WalkerWorker& worker); + struct VarDefPlace { int depth; int index; @@ -195,6 +213,10 @@ namespace triagens { return _dependencies[0]->remaining() + _buffer.size(); } + ExecutionPlan const* getPlan () { + return _exePlan; + } + protected: ExecutionPlan const* _exePlan; std::vector _dependencies; diff --git a/arangod/Aql/ExecutionPlan.cpp b/arangod/Aql/ExecutionPlan.cpp index c36c242c8e..b30ebe58fe 100644 --- a/arangod/Aql/ExecutionPlan.cpp +++ b/arangod/Aql/ExecutionPlan.cpp @@ -117,6 +117,26 @@ void ExecutionPlan::appendAsString (std::string& st, int indent) { st.push_back('>'); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief functionality to walk an execution plan recursively +//////////////////////////////////////////////////////////////////////////////// + +void ExecutionPlan::walk (WalkerWorker& worker) { + worker.before(this); + for (auto it = _dependencies.begin(); + it != _dependencies.end(); + ++it) { + (*it)->walk(worker); + } + if (getType() == SUBQUERY) { + auto p = static_cast(this); + worker.enterSubquery(this, p->getSubquery()); + p->getSubquery()->walk(worker); + worker.leaveSubquery(this, p->getSubquery()); + } + worker.after(this); +} + // ----------------------------------------------------------------------------- // --SECTION-- methods of SingletonPlan // ----------------------------------------------------------------------------- @@ -434,6 +454,22 @@ using namespace triagens::basics; using namespace std; +class MyWorker2 : public triagens::aql::ExecutionPlan::WalkerWorker { + public: + int count; + MyWorker2 () : count(0) {}; + ~MyWorker2 () {}; + void before (triagens::aql::ExecutionPlan* ep) { + std::cout << "Before node of type " << ep->getTypeString() + << std::endl; + count++; + } + void after (triagens::aql::ExecutionPlan* ep) { + std::cout << "After node of type " << ep->getTypeString() + << std::endl; + } +}; + void testExecutionPlans () { Json a(12); Json b(Json::Array); @@ -642,6 +678,11 @@ void testExecutionPlans () { e = n; cout << e->toJson().toString() << endl; + MyWorker2 w; + e->walk(w); + cout << "Count is: " << w.count << endl; + + delete e; } } diff --git a/arangod/Aql/ExecutionPlan.h b/arangod/Aql/ExecutionPlan.h index 00e3813b3b..d2f92ffd46 100644 --- a/arangod/Aql/ExecutionPlan.h +++ b/arangod/Aql/ExecutionPlan.h @@ -225,6 +225,24 @@ namespace triagens { virtual void appendAsString (std::string& st, int indent = 0); +//////////////////////////////////////////////////////////////////////////////// +/// @brief functionality to walk an execution plan recursively +//////////////////////////////////////////////////////////////////////////////// + + class WalkerWorker { + public: + WalkerWorker () {}; + virtual ~WalkerWorker () {}; + virtual void before (ExecutionPlan* eb) {}; + virtual void after (ExecutionPlan* eb) {}; + virtual void enterSubquery (ExecutionPlan* super, + ExecutionPlan* sub) {}; + virtual void leaveSubquery (ExecutionPlan* super, + ExecutionPlan* sub) {}; + }; + + void walk (WalkerWorker& worker); + // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- @@ -812,6 +830,14 @@ namespace triagens { return static_cast(c); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief getter for subquery +//////////////////////////////////////////////////////////////////////////////// + + ExecutionPlan* getSubquery () { + return _subquery; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief private data //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index 053690da31..cef46f03db 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -5401,6 +5401,22 @@ static v8::Handle JS_ParseAql (v8::Arguments const& argv) { /// @brief peng an AQL query //////////////////////////////////////////////////////////////////////////////// +class MyWorker : public triagens::aql::ExecutionBlock::WalkerWorker { + public: + int count; + MyWorker () : count(0) {}; + ~MyWorker () {}; + void before (triagens::aql::ExecutionBlock* eb) { + std::cout << "Before node of type " << eb->getPlan()->getTypeString() + << std::endl; + count++; + } + void after (triagens::aql::ExecutionBlock* eb) { + std::cout << "After node of type " << eb->getPlan()->getTypeString() + << std::endl; + } +}; + static v8::Handle JS_PengAql (v8::Arguments const& argv) { v8::HandleScope scope; @@ -5424,6 +5440,10 @@ static v8::Handle JS_PengAql (v8::Arguments const& argv) { exec->staticAnalysis(); + MyWorker w; + exec->walk(w); + std::cout << "Count is " << w.count << std::endl; + exec->initialize(); exec->execute();