diff --git a/arangod/Aql/Ast.cpp b/arangod/Aql/Ast.cpp index c9a4f2355a..e1dbfb178a 100644 --- a/arangod/Aql/Ast.cpp +++ b/arangod/Aql/Ast.cpp @@ -186,6 +186,7 @@ AstNode* Ast::createNodeRemove (AstNode const* expression, node->addMember(collection); node->addMember(expression); + // TODO: handle options return node; } @@ -200,6 +201,7 @@ AstNode* Ast::createNodeInsert (AstNode const* expression, node->addMember(collection); node->addMember(expression); + // TODO: handle options return node; } @@ -218,6 +220,7 @@ AstNode* Ast::createNodeUpdate (AstNode const* keyExpression, if (keyExpression != nullptr) { node->addMember(keyExpression); } + // TODO: handle options return node; } @@ -237,6 +240,7 @@ AstNode* Ast::createNodeReplace (AstNode const* keyExpression, if (keyExpression != nullptr) { node->addMember(keyExpression); } + // TODO: handle options return node; } diff --git a/arangod/Aql/AstNode.cpp b/arangod/Aql/AstNode.cpp index 856484dc9d..6e293599d9 100644 --- a/arangod/Aql/AstNode.cpp +++ b/arangod/Aql/AstNode.cpp @@ -276,8 +276,8 @@ bool AstNode::isSimple () const { } if (type == NODE_TYPE_ARRAY_ELEMENT) { - auto member = getMember(0); - return member->isSimple(); + auto member = getMember(0); + return member->isSimple(); } return false; diff --git a/arangod/Aql/ExecutionBlock.h b/arangod/Aql/ExecutionBlock.h index 657d57851e..4d7d455acb 100644 --- a/arangod/Aql/ExecutionBlock.h +++ b/arangod/Aql/ExecutionBlock.h @@ -330,16 +330,6 @@ namespace triagens { totalNrRegs++; break; } - case ExecutionNode::PROJECTION: { - nrRegsHere[depth]++; - nrRegs[depth]++; - auto ep = static_cast(eb->getPlanNode()); - TRI_ASSERT(ep != nullptr); - varInfo.insert(make_pair(ep->_outVariable->id, - VarInfo(depth, totalNrRegs))); - totalNrRegs++; - break; - } case ExecutionNode::SUBQUERY: { nrRegsHere[depth]++; nrRegs[depth]++; diff --git a/arangod/Aql/ExecutionEngine.cpp b/arangod/Aql/ExecutionEngine.cpp index cf672ca58a..dc23e469e2 100644 --- a/arangod/Aql/ExecutionEngine.cpp +++ b/arangod/Aql/ExecutionEngine.cpp @@ -30,6 +30,7 @@ #include "Aql/ExecutionEngine.h" #include "Aql/ExecutionBlock.h" #include "Aql/ExecutionNode.h" +#include "Aql/ExecutionPlan.h" #include "Aql/WalkerWorker.h" #include "Utils/Exception.h" diff --git a/arangod/Aql/ExecutionNode.cpp b/arangod/Aql/ExecutionNode.cpp index c12f6cbf8a..462fa0f78c 100644 --- a/arangod/Aql/ExecutionNode.cpp +++ b/arangod/Aql/ExecutionNode.cpp @@ -32,10 +32,49 @@ using namespace triagens::basics; using namespace triagens::aql; +// ----------------------------------------------------------------------------- +// --SECTION-- static initialization +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief type names +//////////////////////////////////////////////////////////////////////////////// + +std::unordered_map const ExecutionNode::TypeNames{ + { static_cast(ILLEGAL), "ExecutionNode (abstract)" }, + { static_cast(SINGLETON), "SingletonNode" }, + { static_cast(ENUMERATE_COLLECTION), "EnumerateCollectionNode" }, + { static_cast(ENUMERATE_LIST), "EnumerateListNode" }, + { static_cast(LIMIT), "LimitNode" }, + { static_cast(CALCULATION), "CalculationNode" }, + { static_cast(SUBQUERY), "SubqueryNode" }, + { static_cast(FILTER), "FilterNode" }, + { static_cast(SORT), "SortNode" }, + { static_cast(AGGREGATE), "AggregateNode" }, + { static_cast(RETURN), "ReturnNode" }, + { static_cast(REMOVE), "RemoveNode" }, + { static_cast(INSERT), "InsertNode" }, + { static_cast(UPDATE), "UpdateNode" }, + { static_cast(REPLACE), "ReplaceNode" } +}; + // ----------------------------------------------------------------------------- // --SECTION-- methods of ExecutionNode // ----------------------------------------------------------------------------- +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the type name of the node +//////////////////////////////////////////////////////////////////////////////// + +std::string ExecutionNode::getTypeString () const { + auto it = TypeNames.find(static_cast(getType())); + if (it != TypeNames.end()) { + return std::string((*it).second); + } + + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_NOT_IMPLEMENTED, "missing type in TypeNames"); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief toJson, export an ExecutionNode to JSON //////////////////////////////////////////////////////////////////////////////// @@ -45,9 +84,9 @@ Json ExecutionNode::toJson (TRI_memory_zone_t* zone) { Json json; Json nodes; try { - nodes = Json(Json::List,10); + nodes = Json(Json::List, 10); toJsonHelper(indexTab, nodes, zone); - json = Json(Json::Array,1) + json = Json(Json::Array, 1) ("nodes", nodes); } catch (std::exception& e) { @@ -71,8 +110,8 @@ void ExecutionNode::appendAsString (std::string& st, int indent) { if (_dependencies.size() != 0) { st.push_back('\n'); for (size_t i = 0; i < _dependencies.size(); i++) { - _dependencies[i]->appendAsString(st, indent+2); - if (i != _dependencies.size()-1) { + _dependencies[i]->appendAsString(st, indent + 2); + if (i != _dependencies.size() - 1) { st.push_back(','); } else { @@ -131,7 +170,7 @@ Json ExecutionNode::toJsonHelperGeneric (std::map& indexTab _dependencies[i]->toJsonHelper(indexTab, nodes, zone); } Json json; - json = Json(Json::Array,2) + json = Json(Json::Array, 2) ("type", Json(getTypeString())); Json deps(Json::List, _dependencies.size()); for (size_t i = 0; i < _dependencies.size(); i++) { @@ -297,36 +336,6 @@ void SubqueryNode::toJsonHelper (std::map& indexTab, indexTab.insert(make_pair(this, len)); } -// ----------------------------------------------------------------------------- -// --SECTION-- methods of ProjectionNode -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @brief toJson, for ProjectionNode -//////////////////////////////////////////////////////////////////////////////// - -void ProjectionNode::toJsonHelper (std::map& indexTab, - triagens::basics::Json& nodes, - TRI_memory_zone_t* zone) { - Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method - if (json.isEmpty()) { - return; - } - Json vec(Json::List,_keepAttributes.size()); - for (auto it = _keepAttributes.begin(); it != _keepAttributes.end(); ++it) { - vec(Json(*it)); - } - - json("inVariable", _inVariable->toJson()) - ("outVariable", _outVariable->toJson()) - ("keepAttributes", vec); - - // And add it: - int len = static_cast(nodes.size()); - nodes(json); - indexTab.insert(make_pair(this, len)); -} - // ----------------------------------------------------------------------------- // --SECTION-- methods of FilterNode // ----------------------------------------------------------------------------- @@ -442,6 +451,118 @@ void ReturnNode::toJsonHelper (std::map& indexTab, indexTab.insert(make_pair(this, len)); } +// ----------------------------------------------------------------------------- +// --SECTION-- methods of RemoveNode +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief toJson +//////////////////////////////////////////////////////////////////////////////// + +void RemoveNode::toJsonHelper (std::map& indexTab, + triagens::basics::Json& nodes, + TRI_memory_zone_t* zone) { + Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method + + if (json.isEmpty()) { + return; + } + + // Now put info about vocbase and cid in there + json("database", Json(_vocbase->_name)) + ("collection", Json(_collname)) + ("outVariable", _outVariable->toJson()); + + // And add it: + int len = static_cast(nodes.size()); + nodes(json); + indexTab.insert(make_pair(this, len)); +} + +// ----------------------------------------------------------------------------- +// --SECTION-- methods of InsertNode +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief toJson +//////////////////////////////////////////////////////////////////////////////// + +void InsertNode::toJsonHelper (std::map& indexTab, + triagens::basics::Json& nodes, + TRI_memory_zone_t* zone) { + Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method + + if (json.isEmpty()) { + return; + } + + // Now put info about vocbase and cid in there + json("database", Json(_vocbase->_name)) + ("collection", Json(_collname)) + ("outVariable", _outVariable->toJson()); + + // And add it: + int len = static_cast(nodes.size()); + nodes(json); + indexTab.insert(make_pair(this, len)); +} + +// ----------------------------------------------------------------------------- +// --SECTION-- methods of UpdateNode +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief toJson +//////////////////////////////////////////////////////////////////////////////// + +void UpdateNode::toJsonHelper (std::map& indexTab, + triagens::basics::Json& nodes, + TRI_memory_zone_t* zone) { + Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method + + if (json.isEmpty()) { + return; + } + + // Now put info about vocbase and cid in there + json("database", Json(_vocbase->_name)) + ("collection", Json(_collname)) + ("outVariable", _outVariable->toJson()); + + // And add it: + int len = static_cast(nodes.size()); + nodes(json); + indexTab.insert(make_pair(this, len)); +} + +// ----------------------------------------------------------------------------- +// --SECTION-- methods of ReplaceNode +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief toJson +//////////////////////////////////////////////////////////////////////////////// + +void ReplaceNode::toJsonHelper (std::map& indexTab, + triagens::basics::Json& nodes, + TRI_memory_zone_t* zone) { + Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method + + if (json.isEmpty()) { + return; + } + + // Now put info about vocbase and cid in there + json("database", Json(_vocbase->_name)) + ("collection", Json(_collname)) + ("outVariable", _outVariable->toJson()); + + // And add it: + int len = static_cast(nodes.size()); + nodes(json); + indexTab.insert(make_pair(this, len)); +} + // Local Variables: // mode: outline-minor // outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" diff --git a/arangod/Aql/ExecutionNode.h b/arangod/Aql/ExecutionNode.h index 38ee87484c..0729689ecf 100644 --- a/arangod/Aql/ExecutionNode.h +++ b/arangod/Aql/ExecutionNode.h @@ -25,8 +25,8 @@ /// @author Copyright 2014, triagens GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// -#ifndef ARANGODB_AQL_EXECUTION_Plan_H -#define ARANGODB_AQL_EXECUTION_Plan_H 1 +#ifndef ARANGODB_AQL_EXECUTION_NODE_H +#define ARANGODB_AQL_EXECUTION_NODE_H 1 #include @@ -78,10 +78,10 @@ namespace triagens { CONCATENATION, MERGE, REMOTE, - INSERT, - REMOVE, - REPLACE, - UPDATE, + INSERT, // done + REMOVE, // done + REPLACE, // done + UPDATE, // done RETURN // done }; @@ -121,17 +121,13 @@ namespace triagens { /// @brief return the type of the node //////////////////////////////////////////////////////////////////////////////// - virtual NodeType getType () const { - return ILLEGAL; - } + virtual NodeType getType () const = 0; //////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string +/// @brief return the type name of the node //////////////////////////////////////////////////////////////////////////////// - virtual std::string getTypeString () const { - return std::string("ExecutionNode (abstract)"); - } + std::string getTypeString () const; //////////////////////////////////////////////////////////////////////////////// /// @brief add a dependency @@ -195,12 +191,20 @@ namespace triagens { /// @brief estimate the cost of the node . . . //////////////////////////////////////////////////////////////////////////////// + double getCost () { + if (_estimatedCost == 0){ + _estimatedCost = estimateCost(); + } + return _estimatedCost; + }; + virtual double estimateCost () = 0; + //TODO nodes should try harder to estimate their own cost, i.e. the cost //of performing the operation of the node . . . //////////////////////////////////////////////////////////////////////////////// -/// @brief TODO what? +/// @brief FIXME what? //////////////////////////////////////////////////////////////////////////////// void walk (WalkerWorker* worker); @@ -211,22 +215,6 @@ namespace triagens { triagens::basics::Json toJson (TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE); -//////////////////////////////////////////////////////////////////////////////// -/// @brief helpers for export to JSON, appends an entry to nodes, indexMap is the -/// map from nodes to indices in list -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- public data -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @brief _estimatedCost = 0 if uninitialised and otherwise stores the result -/// of estimateCost() -//////////////////////////////////////////////////////////////////////////////// - - double _estimatedCost; - // ----------------------------------------------------------------------------- // --SECTION-- protected methods // ----------------------------------------------------------------------------- @@ -253,15 +241,27 @@ namespace triagens { // ----------------------------------------------------------------------------- // --SECTION-- protected variables // ----------------------------------------------------------------------------- + + protected: //////////////////////////////////////////////////////////////////////////////// /// @brief our dependent nodes //////////////////////////////////////////////////////////////////////////////// - protected: - std::vector _dependencies; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief NodeType to string mapping +//////////////////////////////////////////////////////////////////////////////// + static std::unordered_map const TypeNames; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief _estimatedCost = 0 if uninitialised and otherwise stores the result +/// of estimateCost() +//////////////////////////////////////////////////////////////////////////////// + + double _estimatedCost; }; // ----------------------------------------------------------------------------- @@ -269,7 +269,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class SingletonNode, derived from ExecutionNode +/// @brief class SingletonNode //////////////////////////////////////////////////////////////////////////////// class SingletonNode : public ExecutionNode { @@ -283,9 +283,7 @@ namespace triagens { public: - SingletonNode () : ExecutionNode() { - _estimatedCost = 1; - } + SingletonNode () : ExecutionNode() {} //////////////////////////////////////////////////////////////////////////////// /// @brief return the type of the node @@ -295,14 +293,6 @@ namespace triagens { return SINGLETON; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("SingletonNode"); - } - //////////////////////////////////////////////////////////////////////////////// /// @brief export to JSON //////////////////////////////////////////////////////////////////////////////// @@ -326,7 +316,7 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// double estimateCost () { - return _estimatedCost; + return 1; } }; @@ -336,7 +326,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class EnumerateCollectionNode, derived from ExecutionNode +/// @brief class EnumerateCollectionNode //////////////////////////////////////////////////////////////////////////////// class EnumerateCollectionNode : public ExecutionNode { @@ -367,14 +357,6 @@ namespace triagens { return ENUMERATE_COLLECTION; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("EnumerateCollectionNode"); - } - //////////////////////////////////////////////////////////////////////////////// /// @brief export to JSON //////////////////////////////////////////////////////////////////////////////// @@ -399,16 +381,13 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// double estimateCost () { - if (_estimatedCost == 0){ - _estimatedCost = 1000 * _dependencies.at(0)->estimateCost(); - //FIXME improve this estimate . . . - } - return _estimatedCost; + return 1000 * _dependencies.at(0)->getCost(); + //FIXME improve this estimate . . . } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -437,7 +416,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class EnumerateListNode, derived from ExecutionNode +/// @brief class EnumerateListNode //////////////////////////////////////////////////////////////////////////////// class EnumerateListNode : public ExecutionNode { @@ -467,14 +446,6 @@ namespace triagens { return ENUMERATE_LIST; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("EnumerateListNode"); - } - //////////////////////////////////////////////////////////////////////////////// /// @brief export to JSON //////////////////////////////////////////////////////////////////////////////// @@ -498,16 +469,13 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// double estimateCost () { - if (_estimatedCost == 0){ - _estimatedCost = 1000 * _dependencies.at(0)->estimateCost(); - //FIXME improve this estimate . . . - } - return _estimatedCost; + return 1000 * _dependencies.at(0)->getCost(); + //FIXME improve this estimate . . . } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -531,7 +499,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class LimitNode, derived from ExecutionNode +/// @brief class LimitNode //////////////////////////////////////////////////////////////////////////////// class LimitNode : public ExecutionNode { @@ -561,14 +529,6 @@ namespace triagens { return LIMIT; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("LimitNode"); - } - //////////////////////////////////////////////////////////////////////////////// /// @brief export to JSON //////////////////////////////////////////////////////////////////////////////// @@ -593,12 +553,9 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// double estimateCost () { - if (_estimatedCost == 0){ - _estimatedCost = 1.005 * std::min(static_cast(_limit), - _dependencies.at(0)->estimateCost()); - //FIXME improve this estimate . . . - } - return _estimatedCost; + return 1.005 * std::min(static_cast(_limit), + _dependencies.at(0)->getCost()); + //FIXME improve this estimate . . . } //////////////////////////////////////////////////////////////////////////////// @@ -612,114 +569,12 @@ namespace triagens { }; -// ----------------------------------------------------------------------------- -// --SECTION-- class ProjectionNode -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @brief class ProjectionNode, derived from ExecutionNode -//////////////////////////////////////////////////////////////////////////////// - - class ProjectionNode : public ExecutionNode { - - friend class ExecutionBlock; - friend class ProjectionBlock; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief constructor -//////////////////////////////////////////////////////////////////////////////// - - public: - - ProjectionNode (Variable const* inVariable, - Variable const* outVariable, - std::vector keepAttributes) - : ExecutionNode(), _inVariable(inVariable), _outVariable(outVariable), - _keepAttributes(keepAttributes) { - - TRI_ASSERT(inVariable != nullptr); - TRI_ASSERT(outVariable != nullptr); - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node -//////////////////////////////////////////////////////////////////////////////// - - virtual NodeType getType () const { - return PROJECTION; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("ProjectionNode"); - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief export to JSON -//////////////////////////////////////////////////////////////////////////////// - - virtual void toJsonHelper (std::map& indexTab, - triagens::basics::Json& nodes, - TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief clone ExecutionNode recursively -//////////////////////////////////////////////////////////////////////////////// - - virtual ExecutionNode* clone () const { - auto c = new ProjectionNode(_inVariable, _outVariable, _keepAttributes); - cloneDependencies(c); - return static_cast(c); - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief the cost of a projection node is the cost of the unique dependency, -// times a small constant . . . -//////////////////////////////////////////////////////////////////////////////// - - double estimateCost () { - if (_estimatedCost == 0){ - _estimatedCost = 1.005 * _dependencies.at(0)->estimateCost(); - //FIXME improve this estimate . . . - } - return _estimatedCost; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// - - private: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief input variable to read from -//////////////////////////////////////////////////////////////////////////////// - - Variable const* _inVariable; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief output variable to write to -//////////////////////////////////////////////////////////////////////////////// - - Variable const* _outVariable; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief vector of attributes to leave in the object -//////////////////////////////////////////////////////////////////////////////// - - std::vector _keepAttributes; - - }; - // ----------------------------------------------------------------------------- // --SECTION-- class CalculationNode // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class CalculationNode, derived from ExecutionNode +/// @brief class CalculationNode //////////////////////////////////////////////////////////////////////////////// class CalculationNode : public ExecutionNode { @@ -761,14 +616,6 @@ namespace triagens { return CALCULATION; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("CalculationNode"); - } - //////////////////////////////////////////////////////////////////////////////// /// @brief export to JSON //////////////////////////////////////////////////////////////////////////////// @@ -809,16 +656,13 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// double estimateCost () { - if (_estimatedCost == 0){ - _estimatedCost = 2 * _dependencies.at(0)->estimateCost(); - //FIXME improve this estimate . . . - } - return _estimatedCost; + return 2 * _dependencies.at(0)->getCost(); + //FIXME improve this estimate . . . } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -841,7 +685,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class SubqueryNode, derived from ExecutionNode +/// @brief class SubqueryNode //////////////////////////////////////////////////////////////////////////////// class SubqueryNode : public ExecutionNode { @@ -870,14 +714,6 @@ namespace triagens { return SUBQUERY; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("SubqueryNode"); - } - //////////////////////////////////////////////////////////////////////////////// /// @brief export to JSON //////////////////////////////////////////////////////////////////////////////// @@ -910,16 +746,13 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// double estimateCost () { - if (_estimatedCost == 0){ - _estimatedCost = 1.005 * _dependencies.at(0)->estimateCost(); - //FIXME improve this estimate . . . - } - return _estimatedCost; + return 1.005 * _dependencies.at(0)->getCost(); + //FIXME improve this estimate . . . } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -942,7 +775,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class FilterNode, derived from ExecutionNode +/// @brief class FilterNode //////////////////////////////////////////////////////////////////////////////// class FilterNode : public ExecutionNode { @@ -970,14 +803,6 @@ namespace triagens { return FILTER; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("FilterNode"); - } - //////////////////////////////////////////////////////////////////////////////// /// @brief export to JSON //////////////////////////////////////////////////////////////////////////////// @@ -1001,12 +826,9 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// double estimateCost () { - if (_estimatedCost == 0){ - _estimatedCost = _dependencies.at(0)->estimateCost() * 0.105; - //FIXME! 0.005 is the cost of doing the filter node under the - //assumption that it returns 10% of the results of its dependency - } - return _estimatedCost; + return _dependencies.at(0)->getCost() * 0.105; + //FIXME! 0.005 is the cost of doing the filter node under the + //assumption that it returns 10% of the results of its dependency } //////////////////////////////////////////////////////////////////////////////// @@ -1028,7 +850,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class SortNode, derived from ExecutionNode +/// @brief class SortNode //////////////////////////////////////////////////////////////////////////////// class SortNode : public ExecutionNode { @@ -1054,14 +876,6 @@ namespace triagens { return SORT; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("SortNode"); - } - //////////////////////////////////////////////////////////////////////////////// /// @brief export to JSON //////////////////////////////////////////////////////////////////////////////// @@ -1085,16 +899,13 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// double estimateCost () { - if (_estimatedCost == 0){ - double depCost = _dependencies.at(0)->estimateCost(); - _estimatedCost = log(depCost) * depCost; - } - return _estimatedCost; + double depCost = _dependencies.at(0)->getCost(); + return log(depCost) * depCost; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -1113,7 +924,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class AggregateNode, derived from ExecutionNode +/// @brief class AggregateNode //////////////////////////////////////////////////////////////////////////////// class AggregateNode : public ExecutionNode { @@ -1145,14 +956,6 @@ namespace triagens { return AGGREGATE; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("AggregateNode"); - } - //////////////////////////////////////////////////////////////////////////////// /// @brief export to JSON //////////////////////////////////////////////////////////////////////////////// @@ -1176,16 +979,13 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// double estimateCost () { - if (_estimatedCost == 0){ - _estimatedCost = 2 * _dependencies.at(0)->estimateCost(); - //FIXME improve this estimate . . . - } - return _estimatedCost; + return 2 * _dependencies.at(0)->getCost(); + //FIXME improve this estimate . . . } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -1215,7 +1015,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class ReturnNode, derived from ExecutionNode +/// @brief class ReturnNode //////////////////////////////////////////////////////////////////////////////// class ReturnNode : public ExecutionNode { @@ -1243,14 +1043,6 @@ namespace triagens { return RETURN; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("ReturnNode"); - } - //////////////////////////////////////////////////////////////////////////////// /// @brief export to JSON //////////////////////////////////////////////////////////////////////////////// @@ -1274,21 +1066,384 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// double estimateCost () { - if (_estimatedCost == 0){ - _estimatedCost = _dependencies.at(0)->estimateCost(); - } - return _estimatedCost; + return _dependencies.at(0)->getCost(); } +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + + private: + //////////////////////////////////////////////////////////////////////////////// /// @brief we need to know the offset and limit //////////////////////////////////////////////////////////////////////////////// - private: - Variable const* _inVariable; }; + +// ----------------------------------------------------------------------------- +// --SECTION-- class RemoveNode +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief class RemoveNode +//////////////////////////////////////////////////////////////////////////////// + + class RemoveNode : public ExecutionNode { + + friend class ExecutionBlock; + friend class RemoveBlock; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor with a vocbase and a collection name +//////////////////////////////////////////////////////////////////////////////// + + public: + + RemoveNode (TRI_vocbase_t* vocbase, + std::string collname, + Variable const* outVariable) + : ExecutionNode(), _vocbase(vocbase), _collname(collname), + _outVariable(outVariable) { + + TRI_ASSERT(_vocbase != nullptr); + TRI_ASSERT(_outVariable != nullptr); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief return the type of the node +//////////////////////////////////////////////////////////////////////////////// + + virtual NodeType getType () const { + return REMOVE; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief export to JSON +//////////////////////////////////////////////////////////////////////////////// + + virtual void toJsonHelper (std::map& indexTab, + triagens::basics::Json& nodes, + TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief clone ExecutionNode recursively +//////////////////////////////////////////////////////////////////////////////// + + virtual ExecutionNode* clone () const { + auto c = new RemoveNode(_vocbase, _collname, _outVariable); + cloneDependencies(c); + return static_cast(c); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief the cost of a remove node is a multiple of the cost of its unique +/// dependency +//////////////////////////////////////////////////////////////////////////////// + + double estimateCost () { + return 1000 * _dependencies.at(0)->getCost(); + } + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief _vocbase, the database +//////////////////////////////////////////////////////////////////////////////// + + TRI_vocbase_t* _vocbase; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief _collname, the collection name +//////////////////////////////////////////////////////////////////////////////// + + std::string _collname; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief output variable +//////////////////////////////////////////////////////////////////////////////// + + Variable const* _outVariable; + + }; + +// ----------------------------------------------------------------------------- +// --SECTION-- class InsertNode +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief class InsertNode +//////////////////////////////////////////////////////////////////////////////// + + class InsertNode : public ExecutionNode { + + friend class ExecutionBlock; + friend class InsertBlock; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor with a vocbase and a collection name +//////////////////////////////////////////////////////////////////////////////// + + public: + + InsertNode (TRI_vocbase_t* vocbase, + std::string collname, + Variable const* outVariable) + : ExecutionNode(), _vocbase(vocbase), _collname(collname), + _outVariable(outVariable) { + + TRI_ASSERT(_vocbase != nullptr); + TRI_ASSERT(_outVariable != nullptr); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief return the type of the node +//////////////////////////////////////////////////////////////////////////////// + + virtual NodeType getType () const { + return INSERT; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief export to JSON +//////////////////////////////////////////////////////////////////////////////// + + virtual void toJsonHelper (std::map& indexTab, + triagens::basics::Json& nodes, + TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief clone ExecutionNode recursively +//////////////////////////////////////////////////////////////////////////////// + + virtual ExecutionNode* clone () const { + auto c = new InsertNode(_vocbase, _collname, _outVariable); + cloneDependencies(c); + return static_cast(c); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief the cost of a remove node is a multiple of the cost of its unique +/// dependency +//////////////////////////////////////////////////////////////////////////////// + + double estimateCost () { + return 1000 * _dependencies.at(0)->getCost(); //FIXME change this! + } + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief _vocbase, the database +//////////////////////////////////////////////////////////////////////////////// + + TRI_vocbase_t* _vocbase; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief _collname, the collection name +//////////////////////////////////////////////////////////////////////////////// + + std::string _collname; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief output variable +//////////////////////////////////////////////////////////////////////////////// + + Variable const* _outVariable; + + }; + +// ----------------------------------------------------------------------------- +// --SECTION-- class UpdateNode +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief class UpdateNode +//////////////////////////////////////////////////////////////////////////////// + + class UpdateNode : public ExecutionNode { + + friend class ExecutionBlock; + friend class UpdateBlock; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor with a vocbase and a collection name +//////////////////////////////////////////////////////////////////////////////// + + public: + + UpdateNode (TRI_vocbase_t* vocbase, + std::string collname, + Variable const* outVariable) + : ExecutionNode(), _vocbase(vocbase), _collname(collname), + _outVariable(outVariable) { + + TRI_ASSERT(_vocbase != nullptr); + TRI_ASSERT(_outVariable != nullptr); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief return the type of the node +//////////////////////////////////////////////////////////////////////////////// + + virtual NodeType getType () const { + return UPDATE; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief export to JSON +//////////////////////////////////////////////////////////////////////////////// + + virtual void toJsonHelper (std::map& indexTab, + triagens::basics::Json& nodes, + TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief clone ExecutionNode recursively +//////////////////////////////////////////////////////////////////////////////// + + virtual ExecutionNode* clone () const { + auto c = new UpdateNode(_vocbase, _collname, _outVariable); + cloneDependencies(c); + return static_cast(c); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief the cost of a remove node is a multiple of the cost of its unique +/// dependency +//////////////////////////////////////////////////////////////////////////////// + + double estimateCost () { + return 1000 * _dependencies.at(0)->getCost(); //FIXME change this! + } + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief _vocbase, the database +//////////////////////////////////////////////////////////////////////////////// + + TRI_vocbase_t* _vocbase; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief _collname, the collection name +//////////////////////////////////////////////////////////////////////////////// + + std::string _collname; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief output variable +//////////////////////////////////////////////////////////////////////////////// + + Variable const* _outVariable; + + }; + +// ----------------------------------------------------------------------------- +// --SECTION-- class ReplaceNode +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief class ReplaceNode +//////////////////////////////////////////////////////////////////////////////// + + class ReplaceNode : public ExecutionNode { + + friend class ExecutionBlock; + friend class ReplaceBlock; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor with a vocbase and a collection name +//////////////////////////////////////////////////////////////////////////////// + + public: + + ReplaceNode (TRI_vocbase_t* vocbase, + std::string collname, + Variable const* outVariable) + : ExecutionNode(), _vocbase(vocbase), _collname(collname), + _outVariable(outVariable) { + + TRI_ASSERT(_vocbase != nullptr); + TRI_ASSERT(_outVariable != nullptr); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief return the type of the node +//////////////////////////////////////////////////////////////////////////////// + + virtual NodeType getType () const { + return REPLACE; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief export to JSON +//////////////////////////////////////////////////////////////////////////////// + + virtual void toJsonHelper (std::map& indexTab, + triagens::basics::Json& nodes, + TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief clone ExecutionNode recursively +//////////////////////////////////////////////////////////////////////////////// + + virtual ExecutionNode* clone () const { + auto c = new UpdateNode(_vocbase, _collname, _outVariable); + cloneDependencies(c); + return static_cast(c); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief the cost of a remove node is a multiple of the cost of its unique +/// dependency +//////////////////////////////////////////////////////////////////////////////// + + double estimateCost () { + return 1000 * _dependencies.at(0)->getCost(); //FIXME change this! + } + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief _vocbase, the database +//////////////////////////////////////////////////////////////////////////////// + + TRI_vocbase_t* _vocbase; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief _collname, the collection name +//////////////////////////////////////////////////////////////////////////////// + + std::string _collname; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief output variable +//////////////////////////////////////////////////////////////////////////////// + + Variable const* _outVariable; + + }; + + } // namespace triagens::aql } // namespace triagens diff --git a/arangod/Aql/ExecutionPlan.cpp b/arangod/Aql/ExecutionPlan.cpp index 24c6546678..fa824003b5 100644 --- a/arangod/Aql/ExecutionPlan.cpp +++ b/arangod/Aql/ExecutionPlan.cpp @@ -84,7 +84,7 @@ ExecutionPlan* ExecutionPlan::instanciateFromAst (Ast const* ast) { plan->_root = plan->fromNode(ast, root); std::cout << plan->_root->toJson().toString() << "\n"; - std::cout << "ESTIMATED COST = €" << plan->estimateCost() << "\n"; + std::cout << "ESTIMATED COST = €" << plan->getCost() << "\n"; return plan; } @@ -480,11 +480,30 @@ ExecutionNode* ExecutionPlan::fromNodeRemove (Ast const* ast, ExecutionNode* previous, AstNode const* node) { TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_REMOVE); + TRI_ASSERT(node->numMembers() == 2); + + auto collection = node->getMember(0); + auto expression = node->getMember(1); - // TODO - THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); + // collection, expression + char const* collectionName = collection->getStringValue(); + ExecutionNode* en = nullptr; - return nullptr; + if (expression->type == NODE_TYPE_REFERENCE) { + // operand is already a variable + auto v = static_cast(expression->getData()); + TRI_ASSERT(v != nullptr); + en = addNode(new RemoveNode(ast->query()->vocbase(), std::string(collectionName), v)); + } + else { + // operand is some misc expression + auto calc = createTemporaryCalculation(ast, expression); + calc->addDependency(previous); + en = addNode(new RemoveNode(ast->query()->vocbase(), std::string(collectionName), calc->outVariable())); + previous = calc; + } + + return addDependency(previous, en); } //////////////////////////////////////////////////////////////////////////////// @@ -495,11 +514,30 @@ ExecutionNode* ExecutionPlan::fromNodeInsert (Ast const* ast, ExecutionNode* previous, AstNode const* node) { TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_INSERT); + TRI_ASSERT(node->numMembers() == 2); + + auto collection = node->getMember(0); + auto expression = node->getMember(1); - // TODO - THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); + // collection, expression + char const* collectionName = collection->getStringValue(); + ExecutionNode* en = nullptr; - return nullptr; + if (expression->type == NODE_TYPE_REFERENCE) { + // operand is already a variable + auto v = static_cast(expression->getData()); + TRI_ASSERT(v != nullptr); + en = addNode(new InsertNode(ast->query()->vocbase(), std::string(collectionName), v)); + } + else { + // operand is some misc expression + auto calc = createTemporaryCalculation(ast, expression); + calc->addDependency(previous); + en = addNode(new InsertNode(ast->query()->vocbase(), std::string(collectionName), calc->outVariable())); + previous = calc; + } + + return addDependency(previous, en); } //////////////////////////////////////////////////////////////////////////////// @@ -510,11 +548,30 @@ ExecutionNode* ExecutionPlan::fromNodeUpdate (Ast const* ast, ExecutionNode* previous, AstNode const* node) { TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_UPDATE); + TRI_ASSERT(node->numMembers() >= 2); + + auto collection = node->getMember(0); + auto expression = node->getMember(1); - // TODO - THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); + // collection, expression + char const* collectionName = collection->getStringValue(); + ExecutionNode* en = nullptr; - return nullptr; + if (expression->type == NODE_TYPE_REFERENCE) { + // operand is already a variable + auto v = static_cast(expression->getData()); + TRI_ASSERT(v != nullptr); + en = addNode(new UpdateNode(ast->query()->vocbase(), std::string(collectionName), v)); + } + else { + // operand is some misc expression + auto calc = createTemporaryCalculation(ast, expression); + calc->addDependency(previous); + en = addNode(new UpdateNode(ast->query()->vocbase(), std::string(collectionName), calc->outVariable())); + previous = calc; + } + + return addDependency(previous, en); } //////////////////////////////////////////////////////////////////////////////// @@ -525,11 +582,30 @@ ExecutionNode* ExecutionPlan::fromNodeReplace (Ast const* ast, ExecutionNode* previous, AstNode const* node) { TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_REPLACE); + TRI_ASSERT(node->numMembers() >= 2); + + auto collection = node->getMember(0); + auto expression = node->getMember(1); - // TODO - THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); + // collection, expression + char const* collectionName = collection->getStringValue(); + ExecutionNode* en = nullptr; - return nullptr; + if (expression->type == NODE_TYPE_REFERENCE) { + // operand is already a variable + auto v = static_cast(expression->getData()); + TRI_ASSERT(v != nullptr); + en = addNode(new ReplaceNode(ast->query()->vocbase(), std::string(collectionName), v)); + } + else { + // operand is some misc expression + auto calc = createTemporaryCalculation(ast, expression); + calc->addDependency(previous); + en = addNode(new ReplaceNode(ast->query()->vocbase(), std::string(collectionName), calc->outVariable())); + previous = calc; + } + + return addDependency(previous, en); } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Aql/ExecutionPlan.h b/arangod/Aql/ExecutionPlan.h index b017443cc6..699e7c3542 100644 --- a/arangod/Aql/ExecutionPlan.h +++ b/arangod/Aql/ExecutionPlan.h @@ -92,9 +92,9 @@ namespace triagens { /// @brief get the estimated cost . . . //////////////////////////////////////////////////////////////////////////////// - double estimateCost () const { + double getCost () const { TRI_ASSERT(_root != nullptr); - return _root->estimateCost(); + return _root->getCost(); } // -----------------------------------------------------------------------------