From dfe7ec46a586bf888ba9ff22067ef1b3b63a1efe Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Thu, 14 Aug 2014 09:39:58 +0200 Subject: [PATCH 1/3] added RemoveNode --- arangod/Aql/AstNode.cpp | 4 +- arangod/Aql/ExecutionNode.cpp | 38 ++++++-- arangod/Aql/ExecutionNode.h | 165 ++++++++++++++++++++++++++++------ arangod/Aql/ExecutionPlan.cpp | 25 +++++- 4 files changed, 194 insertions(+), 38 deletions(-) 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/ExecutionNode.cpp b/arangod/Aql/ExecutionNode.cpp index c12f6cbf8a..fc213e1a05 100644 --- a/arangod/Aql/ExecutionNode.cpp +++ b/arangod/Aql/ExecutionNode.cpp @@ -45,9 +45,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 +71,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 +131,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++) { @@ -442,6 +442,34 @@ 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)); +} + // Local Variables: // mode: outline-minor // outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" diff --git a/arangod/Aql/ExecutionNode.h b/arangod/Aql/ExecutionNode.h index 9ba22777f7..a9e9463fc7 100644 --- a/arangod/Aql/ExecutionNode.h +++ b/arangod/Aql/ExecutionNode.h @@ -79,7 +79,7 @@ namespace triagens { MERGE, REMOTE, INSERT, - REMOVE, + REMOVE, // done REPLACE, UPDATE, RETURN // done @@ -238,13 +238,13 @@ namespace triagens { // ----------------------------------------------------------------------------- // --SECTION-- protected variables // ----------------------------------------------------------------------------- + + protected: //////////////////////////////////////////////////////////////////////////////// /// @brief our dependent nodes //////////////////////////////////////////////////////////////////////////////// - protected: - std::vector _dependencies; }; @@ -387,9 +387,9 @@ namespace triagens { return 1000 * _dependencies.at(0)->estimateCost(); //FIXME change this! } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -482,9 +482,9 @@ namespace triagens { return 1000 * _dependencies.at(0)->estimateCost(); //FIXME change this, 1000 is arbitrary } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -574,13 +574,18 @@ namespace triagens { _dependencies.at(0)->estimateCost());//FIXME change this? } +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + + private: + //////////////////////////////////////////////////////////////////////////////// /// @brief we need to know the offset and limit //////////////////////////////////////////////////////////////////////////////// - private: - size_t _offset; + size_t _limit; }; @@ -657,9 +662,9 @@ namespace triagens { return 1.005 * _dependencies.at(0)->estimateCost();//FIXME change this? } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -781,9 +786,9 @@ namespace triagens { return 2 * _dependencies.at(0)->estimateCost(); //FIXME change this! } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -878,9 +883,9 @@ namespace triagens { return 1.005 * _dependencies.at(0)->estimateCost();//FIXME change this! } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -1047,9 +1052,9 @@ namespace triagens { return log(depCost) * depCost;//FIXME change this! } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -1134,9 +1139,9 @@ namespace triagens { return 2 * _dependencies.at(0)->estimateCost();//FIXME change this! } -//////////////////////////////////////////////////////////////////////////////// -/// @brief private data -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- private: @@ -1228,15 +1233,119 @@ namespace triagens { return _dependencies.at(0)->estimateCost(); } +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + + private: + //////////////////////////////////////////////////////////////////////////////// /// @brief we need to know the offset and limit //////////////////////////////////////////////////////////////////////////////// - private: - Variable const* _inVariable; }; + +// ----------------------------------------------------------------------------- +// --SECTION-- class RemoveCollectionNode +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief class RemoveNode, derived from ExecutionNode +//////////////////////////////////////////////////////////////////////////////// + + 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 return the type of the node as a string +//////////////////////////////////////////////////////////////////////////////// + + virtual std::string getTypeString () const { + return std::string("RemoveNode"); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @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 () const { + return 1000 * _dependencies.at(0)->estimateCost(); //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 f0bba48896..75f5a50a82 100644 --- a/arangod/Aql/ExecutionPlan.cpp +++ b/arangod/Aql/ExecutionPlan.cpp @@ -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); } //////////////////////////////////////////////////////////////////////////////// From 1ad300cee52cdcecd337d783d34be429e7c2138a Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Thu, 14 Aug 2014 10:23:53 +0200 Subject: [PATCH 2/3] added more node types --- arangod/Aql/Ast.cpp | 4 + arangod/Aql/ExecutionBlock.h | 10 - arangod/Aql/ExecutionEngine.cpp | 1 + arangod/Aql/ExecutionNode.cpp | 153 ++++++++-- arangod/Aql/ExecutionNode.h | 511 ++++++++++++++++++-------------- arangod/Aql/ExecutionPlan.cpp | 75 ++++- 6 files changed, 490 insertions(+), 264 deletions(-) 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/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 fc213e1a05..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 //////////////////////////////////////////////////////////////////////////////// @@ -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 // ----------------------------------------------------------------------------- @@ -470,6 +479,90 @@ void RemoveNode::toJsonHelper (std::map& indexTab, 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 a9e9463fc7..3853a0368f 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, + INSERT, // done REMOVE, // done - REPLACE, - UPDATE, + 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 @@ -207,11 +203,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-- protected methods // ----------------------------------------------------------------------------- @@ -247,6 +238,12 @@ namespace triagens { std::vector _dependencies; +//////////////////////////////////////////////////////////////////////////////// +/// @brief NodeType to string mapping +//////////////////////////////////////////////////////////////////////////////// + + static std::unordered_map const TypeNames; + }; // ----------------------------------------------------------------------------- @@ -254,7 +251,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class SingletonNode, derived from ExecutionNode +/// @brief class SingletonNode //////////////////////////////////////////////////////////////////////////////// class SingletonNode : public ExecutionNode { @@ -279,14 +276,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 //////////////////////////////////////////////////////////////////////////////// @@ -320,7 +309,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class EnumerateCollectionNode, derived from ExecutionNode +/// @brief class EnumerateCollectionNode //////////////////////////////////////////////////////////////////////////////// class EnumerateCollectionNode : public ExecutionNode { @@ -352,14 +341,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 //////////////////////////////////////////////////////////////////////////////// @@ -418,7 +399,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class EnumerateListNode, derived from ExecutionNode +/// @brief class EnumerateListNode //////////////////////////////////////////////////////////////////////////////// class EnumerateListNode : public ExecutionNode { @@ -448,14 +429,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 //////////////////////////////////////////////////////////////////////////////// @@ -508,7 +481,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class LimitNode, derived from ExecutionNode +/// @brief class LimitNode //////////////////////////////////////////////////////////////////////////////// class LimitNode : public ExecutionNode { @@ -538,14 +511,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 //////////////////////////////////////////////////////////////////////////////// @@ -590,110 +555,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 () const { - return 1.005 * _dependencies.at(0)->estimateCost();//FIXME change this? - } - -// ----------------------------------------------------------------------------- -// --SECTION-- private variables -// ----------------------------------------------------------------------------- - - 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 { @@ -735,14 +602,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 //////////////////////////////////////////////////////////////////////////////// @@ -811,7 +670,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class SubqueryNode, derived from ExecutionNode +/// @brief class SubqueryNode //////////////////////////////////////////////////////////////////////////////// class SubqueryNode : public ExecutionNode { @@ -840,14 +699,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 //////////////////////////////////////////////////////////////////////////////// @@ -908,7 +759,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class FilterNode, derived from ExecutionNode +/// @brief class FilterNode //////////////////////////////////////////////////////////////////////////////// class FilterNode : public ExecutionNode { @@ -936,14 +787,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 //////////////////////////////////////////////////////////////////////////////// @@ -991,7 +834,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class SortNode, derived from ExecutionNode +/// @brief class SortNode //////////////////////////////////////////////////////////////////////////////// class SortNode : public ExecutionNode { @@ -1017,14 +860,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 //////////////////////////////////////////////////////////////////////////////// @@ -1073,7 +908,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class AggregateNode, derived from ExecutionNode +/// @brief class AggregateNode //////////////////////////////////////////////////////////////////////////////// class AggregateNode : public ExecutionNode { @@ -1105,14 +940,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 //////////////////////////////////////////////////////////////////////////////// @@ -1171,7 +998,7 @@ namespace triagens { // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class ReturnNode, derived from ExecutionNode +/// @brief class ReturnNode //////////////////////////////////////////////////////////////////////////////// class ReturnNode : public ExecutionNode { @@ -1199,14 +1026,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 //////////////////////////////////////////////////////////////////////////////// @@ -1248,11 +1067,11 @@ namespace triagens { }; // ----------------------------------------------------------------------------- -// --SECTION-- class RemoveCollectionNode +// --SECTION-- class RemoveNode // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// -/// @brief class RemoveNode, derived from ExecutionNode +/// @brief class RemoveNode //////////////////////////////////////////////////////////////////////////////// class RemoveNode : public ExecutionNode { @@ -1284,14 +1103,6 @@ namespace triagens { return REMOVE; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the type of the node as a string -//////////////////////////////////////////////////////////////////////////////// - - virtual std::string getTypeString () const { - return std::string("RemoveNode"); - } - //////////////////////////////////////////////////////////////////////////////// /// @brief export to JSON //////////////////////////////////////////////////////////////////////////////// @@ -1337,6 +1148,276 @@ namespace triagens { 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 () const { + return 1000 * _dependencies.at(0)->estimateCost(); //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 () const { + return 1000 * _dependencies.at(0)->estimateCost(); //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 () const { + return 1000 * _dependencies.at(0)->estimateCost(); //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 //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Aql/ExecutionPlan.cpp b/arangod/Aql/ExecutionPlan.cpp index 75f5a50a82..fbfdceb648 100644 --- a/arangod/Aql/ExecutionPlan.cpp +++ b/arangod/Aql/ExecutionPlan.cpp @@ -514,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); } //////////////////////////////////////////////////////////////////////////////// @@ -529,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); } //////////////////////////////////////////////////////////////////////////////// @@ -544,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); } //////////////////////////////////////////////////////////////////////////////// From f911cd254b843ca1facc2d97a2eea822ac1f7421 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Thu, 14 Aug 2014 10:29:54 +0200 Subject: [PATCH 3/3] fixed bug --- arangod/Aql/ExecutionPlan.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arangod/Aql/ExecutionPlan.cpp b/arangod/Aql/ExecutionPlan.cpp index fbfdceb648..60a90934cf 100644 --- a/arangod/Aql/ExecutionPlan.cpp +++ b/arangod/Aql/ExecutionPlan.cpp @@ -548,7 +548,7 @@ 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); + TRI_ASSERT(node->numMembers() >= 2); auto collection = node->getMember(0); auto expression = node->getMember(1); @@ -582,7 +582,7 @@ 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); + TRI_ASSERT(node->numMembers() >= 2); auto collection = node->getMember(0); auto expression = node->getMember(1);