diff --git a/arangod/Aql/AstNode.cpp b/arangod/Aql/AstNode.cpp index 142350c960..b2be001de6 100644 --- a/arangod/Aql/AstNode.cpp +++ b/arangod/Aql/AstNode.cpp @@ -28,6 +28,7 @@ //////////////////////////////////////////////////////////////////////////////// #include "Aql/AstNode.h" +#include "Aql/Scopes.h" using namespace triagens::aql; @@ -74,8 +75,7 @@ void AstNode::toJson (TRI_json_t* json, // dump node type TRI_Insert3ArrayJson(zone, node, "type", TRI_CreateStringCopyJson(zone, typeString().c_str())); - if (type == NODE_TYPE_VARIABLE || - type == NODE_TYPE_REFERENCE || + if (type == NODE_TYPE_REFERENCE || type == NODE_TYPE_COLLECTION || type == NODE_TYPE_PARAMETER || type == NODE_TYPE_ATTRIBUTE_ACCESS || @@ -107,6 +107,13 @@ void AstNode::toJson (TRI_json_t* json, } } } + + if (type == NODE_TYPE_VARIABLE) { + auto variable = static_cast(getData()); + + TRI_Insert3ArrayJson(zone, node, "name", TRI_CreateStringCopyJson(zone, variable->name.c_str())); + TRI_Insert3ArrayJson(zone, node, "id", TRI_CreateNumberJson(zone, static_cast(variable->id))); + } // dump sub-nodes size_t const n = members._length; diff --git a/arangod/Aql/AstNode.h b/arangod/Aql/AstNode.h index 857fab4163..2444175aa3 100644 --- a/arangod/Aql/AstNode.h +++ b/arangod/Aql/AstNode.h @@ -61,6 +61,7 @@ namespace triagens { double _double; bool _bool; char const* _string; + void* _data; } value; AstNodeValueType type; }; @@ -287,6 +288,22 @@ namespace triagens { value.value._string = v; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief return the data value of a node +//////////////////////////////////////////////////////////////////////////////// + + inline void* getData () const { + return value.value._data; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief set the data value of a node +//////////////////////////////////////////////////////////////////////////////// + + inline void setData (void* v) { + value.value._data = v; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief return the type name of a node //////////////////////////////////////////////////////////////////////////////// @@ -299,9 +316,12 @@ namespace triagens { public: - TRI_vector_pointer_t members; AstNodeType const type; AstNodeValue value; + + private: + + TRI_vector_pointer_t members; }; } diff --git a/arangod/Aql/ParseResult.h b/arangod/Aql/ParseResult.h index b79192a1e6..10c8e07b52 100644 --- a/arangod/Aql/ParseResult.h +++ b/arangod/Aql/ParseResult.h @@ -41,14 +41,18 @@ namespace triagens { // ----------------------------------------------------------------------------- struct ParseResult { + ParseResult () = delete; + + ParseResult& operator= (ParseResult const& other) = delete; + ParseResult (ParseResult&& other) { + code = other.code; + explanation = other.explanation; json = other.json; zone = other.zone; other.json = nullptr; } - ParseResult& operator= (ParseResult const& other) = delete; - ParseResult (int code, std::string const& explanation) : code(code), @@ -58,7 +62,9 @@ namespace triagens { } ParseResult (TRI_memory_zone_t* zone) - : zone(zone), + : code(TRI_ERROR_NO_ERROR), + explanation(), + zone(zone), json(nullptr) { } diff --git a/arangod/Aql/Parser.cpp b/arangod/Aql/Parser.cpp index 3043a3130e..caa06dae8f 100644 --- a/arangod/Aql/Parser.cpp +++ b/arangod/Aql/Parser.cpp @@ -128,6 +128,7 @@ ParseResult Parser::parse () { auto error = _query->error(); result.code = error->code; result.explanation = error->explanation; + return result; } diff --git a/arangod/Aql/QueryAst.cpp b/arangod/Aql/QueryAst.cpp index 673039aebf..b63d0685de 100644 --- a/arangod/Aql/QueryAst.cpp +++ b/arangod/Aql/QueryAst.cpp @@ -103,7 +103,7 @@ TRI_json_t* QueryAst::toJson (TRI_memory_zone_t* zone) { void QueryAst::addOperation (AstNode* node) { TRI_ASSERT(_root != nullptr); - TRI_PushBackVectorPointer(&_root->members, (void*) node); + _root->addMember(node); } //////////////////////////////////////////////////////////////////////////////// @@ -352,7 +352,8 @@ AstNode* QueryAst::createNodeVariable (char const* name, AstNode* node = createNode(NODE_TYPE_VARIABLE); node->setStringValue(name); - _scopes.addVariable(name, isUserDefined); + auto variable = _scopes.addVariable(name, isUserDefined); + node->setData(static_cast(variable)); return node; } @@ -666,10 +667,23 @@ void QueryAst::injectBindParameters (BindParameters& parameters) { if (*param == '@') { // collection parameter TRI_ASSERT(TRI_IsStringJson(value)); - + + bool isWriteCollection = false; + if (_writeCollection != nullptr && + _writeCollection->type == NODE_TYPE_PARAMETER && + strcmp(param, _writeCollection->getStringValue()) == 0) { + isWriteCollection = true; + } + // turn node into a collection node char const* name = registerString(value->_value._string.data, value->_value._string.length - 1, false); + node = createNodeCollection(name); + + if (isWriteCollection) { + // this was the bind parameter that contained the collection to update + _writeCollection = node; + } } else { node = nodeFromJson((*it).second); diff --git a/arangod/Aql/QueryAst.h b/arangod/Aql/QueryAst.h index 002f739be3..21de358e28 100644 --- a/arangod/Aql/QueryAst.h +++ b/arangod/Aql/QueryAst.h @@ -112,6 +112,7 @@ namespace triagens { inline void setWriteCollection (AstNode const* node) { TRI_ASSERT(node->type == NODE_TYPE_COLLECTION || node->type == NODE_TYPE_PARAMETER); + _writeCollection = node; } diff --git a/arangod/Aql/Scopes.cpp b/arangod/Aql/Scopes.cpp index 25763aaf05..8a4a1581e1 100644 --- a/arangod/Aql/Scopes.cpp +++ b/arangod/Aql/Scopes.cpp @@ -82,9 +82,9 @@ std::string Scope::typeName () const { /// @brief adds a variable to the scope //////////////////////////////////////////////////////////////////////////////// -void Scope::addVariable (std::string const& name, - size_t id, - bool isUserDefined) { +Variable* Scope::addVariable (std::string const& name, + size_t id, + bool isUserDefined) { auto variable = new Variable(name, id, isUserDefined); try { @@ -94,7 +94,9 @@ void Scope::addVariable (std::string const& name, // prevent memleak delete variable; THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); - } + } + + return variable; } //////////////////////////////////////////////////////////////////////////////// @@ -198,8 +200,8 @@ void Scopes::endNested () { /// @brief adds a variable to the current scope //////////////////////////////////////////////////////////////////////////////// -bool Scopes::addVariable (char const* name, - bool isUserDefined) { +Variable* Scopes::addVariable (char const* name, + bool isUserDefined) { TRI_ASSERT(! _activeScopes.empty()); for (auto it = _activeScopes.rbegin(); it != _activeScopes.rend(); ++it) { @@ -207,12 +209,13 @@ bool Scopes::addVariable (char const* name, if (scope->existsVariable(name)) { // duplicate variable name - return false; + return 0; } } - _activeScopes.back()->addVariable(std::string(name), ++_variableId, isUserDefined); - return true; + size_t id = ++_variableId; + + return _activeScopes.back()->addVariable(std::string(name), id, isUserDefined); } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Aql/Scopes.h b/arangod/Aql/Scopes.h index 10c8c4836d..a7b4381d7e 100644 --- a/arangod/Aql/Scopes.h +++ b/arangod/Aql/Scopes.h @@ -35,13 +35,6 @@ namespace triagens { namespace aql { - template - struct CharComparer : public binary_function { - bool operator () (T const& lhs, T const& rhs) const { - return strcmp(lhs, rhs) == 0; - } - }; - // ----------------------------------------------------------------------------- // --SECTION-- struct Variable // ----------------------------------------------------------------------------- @@ -122,9 +115,9 @@ namespace triagens { /// @brief adds a variable to the scope //////////////////////////////////////////////////////////////////////////////// - void addVariable (std::string const&, - size_t, - bool); + Variable* addVariable (std::string const&, + size_t, + bool); //////////////////////////////////////////////////////////////////////////////// /// @brief checks if a variable exists in the scope @@ -207,8 +200,8 @@ namespace triagens { /// @brief adds a variable to the current scope //////////////////////////////////////////////////////////////////////////////// - bool addVariable (char const*, - bool); + Variable* addVariable (char const*, + bool); //////////////////////////////////////////////////////////////////////////////// /// @brief checks whether a variable exists in any scope