diff --git a/arangod/Aql/QueryResult.h b/arangod/Aql/QueryResult.h index 4a19ee5e0b..34b44292db 100644 --- a/arangod/Aql/QueryResult.h +++ b/arangod/Aql/QueryResult.h @@ -46,7 +46,6 @@ struct QueryResult { bindParameters = other.bindParameters; collectionNames = other.collectionNames; - } QueryResult(int code, std::string const& details) @@ -61,8 +60,7 @@ struct QueryResult { QueryResult() : QueryResult(TRI_ERROR_NO_ERROR) {} - virtual ~QueryResult() { - } + virtual ~QueryResult() {} int code; bool cached; diff --git a/arangod/CMakeLists.txt b/arangod/CMakeLists.txt index 0f3653ab91..98d34c9a58 100644 --- a/arangod/CMakeLists.txt +++ b/arangod/CMakeLists.txt @@ -249,7 +249,6 @@ add_executable(${BIN_ARANGOD} V8Server/v8-vocindex.cpp VocBase/DatafileStatistics.cpp VocBase/Ditch.cpp - VocBase/DocumentAccessor.cpp VocBase/ExampleMatcher.cpp VocBase/Graphs.cpp VocBase/KeyGenerator.cpp diff --git a/arangod/Cluster/ClusterTraverser.cpp b/arangod/Cluster/ClusterTraverser.cpp index 1a34184f48..aa63301a5a 100644 --- a/arangod/Cluster/ClusterTraverser.cpp +++ b/arangod/Cluster/ClusterTraverser.cpp @@ -300,7 +300,7 @@ bool ClusterTraverser::vertexMatchesCondition( std::vector const& exp) { for (auto const& e : exp) { if (!e->isEdgeAccess) { - if (v.isNone() || !e->matchesCheck(v)) { + if (v.isNone() || !e->matchesCheck(_trx, v)) { ++_filteredPaths; return false; } diff --git a/arangod/RestHandler/RestEdgesHandler.cpp b/arangod/RestHandler/RestEdgesHandler.cpp index d9dc4884f7..17f7f7b3b2 100644 --- a/arangod/RestHandler/RestEdgesHandler.cpp +++ b/arangod/RestHandler/RestEdgesHandler.cpp @@ -121,7 +121,7 @@ bool RestEdgesHandler::getEdgesForVertex( if (!expressions.empty()) { for (auto& exp : expressions) { if (exp->isEdgeAccess && - !exp->matchesCheck(edge)) { + !exp->matchesCheck(&trx, edge)) { ++filtered; add = false; break; diff --git a/arangod/RestHandler/RestSimpleHandler.cpp b/arangod/RestHandler/RestSimpleHandler.cpp index 059e04cf09..83b1d0a83e 100644 --- a/arangod/RestHandler/RestSimpleHandler.cpp +++ b/arangod/RestHandler/RestSimpleHandler.cpp @@ -29,6 +29,7 @@ #include "Basics/ScopeGuard.h" #include "Basics/VelocyPackHelper.h" #include "Basics/VPackStringBufferAdapter.h" +#include "Utils/SingleCollectionTransaction.h" #include "VocBase/Traverser.h" #include @@ -395,12 +396,16 @@ void RestSimpleHandler::lookupByKeys(VPackSlice const& slice) { result.add(VPackValue("documents")); std::vector filteredIds; +#warning TODO: fixme + // just needed to build the result + SingleCollectionTransaction trx(StandaloneTransactionContext::Create(_vocbase), collectionName, TRI_TRANSACTION_READ); + result.openArray(); for (auto const& tmp : VPackArrayIterator(qResult)) { if (!tmp.isNone()) { bool add = true; for (auto& e : expressions) { - if (!e->isEdgeAccess && !e->matchesCheck(tmp)) { + if (!e->isEdgeAccess && !e->matchesCheck(&trx, tmp)) { add = false; std::string _id = arangodb::basics::VelocyPackHelper::checkAndGetStringValue( diff --git a/arangod/V8Server/V8Traverser.cpp b/arangod/V8Server/V8Traverser.cpp index 34f039cc9f..7e12b7b3f4 100644 --- a/arangod/V8Server/V8Traverser.cpp +++ b/arangod/V8Server/V8Traverser.cpp @@ -849,7 +849,7 @@ bool DepthFirstTraverser::edgeMatchesConditions(VPackSlice e, size_t depth) { for (auto const& exp : it->second) { TRI_ASSERT(exp != nullptr); - if (exp->isEdgeAccess && !exp->matchesCheck(e)) { + if (exp->isEdgeAccess && !exp->matchesCheck(_trx, e)) { ++_filteredPaths; return false; } @@ -891,7 +891,7 @@ bool DepthFirstTraverser::vertexMatchesConditions(std::string const& v, vertex = it->second; } } - if (!exp->matchesCheck(VPackSlice(vertex->data()))) { + if (!exp->matchesCheck(_trx, VPackSlice(vertex->data()))) { ++_filteredPaths; return false; } @@ -942,7 +942,7 @@ void DepthFirstTraverser::setStartVertex( vertex = result.buffer; _vertices.emplace(v, vertex); } - if (!exp->matchesCheck(VPackSlice(vertex->data()))) { + if (!exp->matchesCheck(_trx, VPackSlice(vertex->data()))) { ++_filteredPaths; _done = true; return; diff --git a/arangod/VocBase/DocumentAccessor.cpp b/arangod/VocBase/DocumentAccessor.cpp deleted file mode 100644 index 1dbb80d3eb..0000000000 --- a/arangod/VocBase/DocumentAccessor.cpp +++ /dev/null @@ -1,418 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// DISCLAIMER -/// -/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany -/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// -/// Copyright holder is ArangoDB GmbH, Cologne, Germany -/// -/// @author Jan Steemann -//////////////////////////////////////////////////////////////////////////////// - -#include "DocumentAccessor.h" -#include "Basics/conversions.h" -#include "Basics/Exceptions.h" -#include "Basics/VelocyPackHelper.h" -#include "Utils/CollectionNameResolver.h" - -DocumentAccessor::DocumentAccessor( - arangodb::CollectionNameResolver const* resolver, - TRI_document_collection_t* document, TRI_doc_mptr_t const* mptr) - : _resolver(resolver), - _document(document), - _mptr(mptr), - _json(), - _current(nullptr) { - TRI_ASSERT(mptr != nullptr); -} - -DocumentAccessor::DocumentAccessor(TRI_json_t const* json) - : _resolver(nullptr), - _document(nullptr), - _mptr(nullptr), - _json(), - _current(json) { - TRI_ASSERT(_current != nullptr); -} - -DocumentAccessor::DocumentAccessor(VPackSlice const& slice) - : _resolver(nullptr), - _document(nullptr), - _mptr(nullptr), - _json(), - _current(nullptr) { - _current = arangodb::basics::VelocyPackHelper::velocyPackToJson(slice); - TRI_ASSERT(_current != nullptr); -} - -DocumentAccessor::~DocumentAccessor() {} - -bool DocumentAccessor::hasKey(std::string const& attribute) const { - if (!isObject()) { - return false; - } - - if (_current == nullptr) { - if (attribute.size() > 1 && attribute[0] == '_') { - if (attribute == TRI_VOC_ATTRIBUTE_ID || - attribute == TRI_VOC_ATTRIBUTE_KEY || - attribute == TRI_VOC_ATTRIBUTE_REV) { - return true; - } - -#if 0 - // TODO - if (TRI_IS_EDGE_MARKER(_mptr) && (attribute == TRI_VOC_ATTRIBUTE_FROM || - attribute == TRI_VOC_ATTRIBUTE_TO)) { - return true; - } -#endif - } - - return false; - } - - return (TRI_LookupObjectJson(_current, attribute.c_str()) != nullptr); -} - -bool DocumentAccessor::isObject() const { - if (_current != nullptr) { - return TRI_IsObjectJson(_current); - } - - // ok, must be a document/edge - return true; -} - -bool DocumentAccessor::isArray() const { - if (_current != nullptr) { - return TRI_IsArrayJson(_current); - } - - // ok, must be a document/edge - return false; -} - -size_t DocumentAccessor::length() const { - if (!isArray()) { - return 0; - } - // ok, we have confirmed this is an array - TRI_ASSERT(_current != nullptr); - if (_current != nullptr) { - return TRI_LengthArrayJson(_current); - } - return 0; -} - -DocumentAccessor& DocumentAccessor::get(std::string const& name) { - return get(name.c_str(), name.size()); -} - -DocumentAccessor& DocumentAccessor::get(char const* name, size_t nameLength) { - if (_current == nullptr) { - // a document, we need the access its attributes using special methods - lookupDocumentAttribute(name, nameLength); - } else { - // already a JSON - lookupJsonAttribute(name, nameLength); - } - - return *this; -} - -DocumentAccessor& DocumentAccessor::at(int64_t index) { - if (isArray()) { - size_t length = TRI_LengthArrayJson(_current); - - if (index < 0) { - // a negative position is allowed - index = static_cast(length) + index; - } - - if (index >= 0 && index < static_cast(length)) { - // only look up the value if it is within array bounds - TRI_json_t const* found = - TRI_LookupArrayJson(_current, static_cast(index)); - - if (found != nullptr) { - _current = found; - return *this; - } - } - // fall-through intentional - } - - setToNull(); - return *this; -} - -arangodb::basics::Json DocumentAccessor::toJson() { -#if 0 - if (_current == nullptr) { - // we're still pointing to the original document - auto shaper = _document->getShaper(); - - // fetch document from mptr - TRI_shaped_json_t shaped; - TRI_EXTRACT_SHAPED_JSON_MARKER(shaped, _mptr->getDataPtr()); - arangodb::basics::Json json(shaper->memoryZone(), - TRI_JsonShapedJson(shaper, &shaped)); - - // add internal attributes - - // _id, _key, _rev - char const* key = TRI_EXTRACT_MARKER_KEY(_mptr); - std::string id(_resolver->getCollectionName(_document->_info.id())); - id.push_back('/'); - id.append(key); - json(TRI_VOC_ATTRIBUTE_ID, arangodb::basics::Json(id)); - json(TRI_VOC_ATTRIBUTE_REV, - arangodb::basics::Json(std::to_string(TRI_EXTRACT_MARKER_RID(_mptr)))); - json(TRI_VOC_ATTRIBUTE_KEY, arangodb::basics::Json(key)); - -#if 0 - // TODO - if (TRI_IS_EDGE_MARKER(_mptr)) { - // _from - std::string from(_resolver->getCollectionNameCluster( - TRI_EXTRACT_MARKER_FROM_CID(_mptr))); - from.push_back('/'); - from.append(TRI_EXTRACT_MARKER_FROM_KEY(_mptr)); - json(TRI_VOC_ATTRIBUTE_FROM, arangodb::basics::Json(from)); - - // _to - std::string to(_resolver->getCollectionNameCluster( - TRI_EXTRACT_MARKER_TO_CID(_mptr))); - to.push_back('/'); - to.append(TRI_EXTRACT_MARKER_TO_KEY(_mptr)); - json(TRI_VOC_ATTRIBUTE_TO, arangodb::basics::Json(to)); - } -#endif - - return json; - } - - if (_current == _json.get()) { - // _current points at the JSON that we own - - // steal the JSON - TRI_json_t* value = _json.release(); - setToNull(); - return arangodb::basics::Json(TRI_UNKNOWN_MEM_ZONE, value); - } - - TRI_json_t* copy = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, _current); - - if (copy != nullptr) { - _json.release(); - return arangodb::basics::Json(TRI_UNKNOWN_MEM_ZONE, copy); - } - // fall-through intentional -#endif - return arangodb::basics::Json(arangodb::basics::Json::Null); -} - -void DocumentAccessor::setToNull() { - // check if already null - if (_current != nullptr && _current->_type == TRI_JSON_NULL) { - // already null. done! - return; - } - - _json.reset(TRI_CreateNullJson(TRI_UNKNOWN_MEM_ZONE)); - if (_json.get() == nullptr) { - THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); - } - - _current = _json.get(); - TRI_ASSERT(_current != nullptr); -} - -void DocumentAccessor::lookupJsonAttribute(char const* name, - size_t nameLength) { - TRI_ASSERT(_current != nullptr); - - if (!isObject()) { - setToNull(); - return; - } - - TRI_json_t const* value = TRI_LookupObjectJson(_current, name); - - if (value == nullptr) { - // attribute not found - setToNull(); - } else { - // found - _current = value; - } -} - -void DocumentAccessor::lookupDocumentAttribute(char const* name, - size_t nameLength) { - if (*name == '_' && name[1] != '\0') { - if (name[1] == 'k' && nameLength == 4 && - memcmp(name, TRI_VOC_ATTRIBUTE_KEY, nameLength) == 0) { - // _key value is copied into JSON - char const* key = TRI_EXTRACT_MARKER_KEY(_mptr); - if (key == nullptr) { - setToNull(); - return; - } - _json.reset( - TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, key, strlen(key))); - - if (_json.get() == nullptr) { - THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); - } - - _current = _json.get(); - return; - } - - if (name[1] == 'i' && nameLength == 3 && - memcmp(name, TRI_VOC_ATTRIBUTE_ID, nameLength) == 0) { - // _id - char buffer[512]; // big enough for max key length + max collection name - // length - size_t pos = - _resolver->getCollectionName(&buffer[0], _document->_info.id()); - buffer[pos++] = '/'; - char const* key = TRI_EXTRACT_MARKER_KEY(_mptr); - if (key == nullptr) { - setToNull(); - return; - } - size_t len = strlen(key); - memcpy(&buffer[pos], key, len); - buffer[pos + len] = '\0'; - _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], - pos + len)); - if (_json.get() == nullptr) { - THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); - } - _current = _json.get(); - return; - } - -#if 0 - if (name[1] == 'r' && nameLength == 4 && - memcmp(name, TRI_VOC_ATTRIBUTE_REV, nameLength) == 0) { - // _rev - char buffer[21]; - TRI_voc_rid_t rid = TRI_EXTRACT_MARKER_RID(_mptr); - size_t len = TRI_StringUInt64InPlace(rid, &buffer[0]); - _json.reset( - TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], len)); - if (_json.get() == nullptr) { - THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); - } - _current = _json.get(); - return; - } -#endif - -#if 0 - // TODO - if (TRI_IS_EDGE_MARKER(_mptr)) { - if (name[1] == 'f' && nameLength == 5 && - memcmp(name, TRI_VOC_ATTRIBUTE_FROM, nameLength) == 0) { - // _from - char buffer[512]; // big enough for max key length + max collection - // name length - size_t pos = _resolver->getCollectionNameCluster( - &buffer[0], TRI_EXTRACT_MARKER_FROM_CID(_mptr)); - buffer[pos++] = '/'; - char const* key = TRI_EXTRACT_MARKER_FROM_KEY(_mptr); - if (key == nullptr) { - setToNull(); - return; - } - size_t len = strlen(key); - memcpy(&buffer[pos], key, len); - buffer[pos + len] = '\0'; - _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], - pos + len)); - if (_json.get() == nullptr) { - THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); - } - _current = _json.get(); - return; - } - - if (name[1] == 't' && nameLength == 3 && - memcmp(name, TRI_VOC_ATTRIBUTE_TO, nameLength) == 0) { - // to - char buffer[512]; // big enough for max key length + max collection - // name length - size_t pos = _resolver->getCollectionNameCluster( - &buffer[0], TRI_EXTRACT_MARKER_TO_CID(_mptr)); - buffer[pos++] = '/'; - char const* key = TRI_EXTRACT_MARKER_TO_KEY(_mptr); - if (key == nullptr) { - setToNull(); - return; - } - size_t len = strlen(key); - memcpy(&buffer[pos], key, len); - buffer[pos + len] = '\0'; - _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], - pos + len)); - if (_json.get() == nullptr) { - THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); - } - _current = _json.get(); - return; - } - } -#endif - - // fall-through intentional - } - -#if 0 - auto shaper = _document->getShaper(); - - TRI_shape_pid_t pid = shaper->lookupAttributePathByName(name); - - if (pid == 0) { - // attribute does not exist - setToNull(); - return; - } - - // attribute exists - TRI_shaped_json_t document; - TRI_EXTRACT_SHAPED_JSON_MARKER(document, _mptr->getDataPtr()); - - TRI_shaped_json_t json; - TRI_shape_t const* shape; - - bool ok = shaper->extractShapedJson(&document, 0, pid, &json, &shape); - - if (ok && shape != nullptr) { - _json.reset(TRI_JsonShapedJson(shaper, &json)); - if (_json.get() == nullptr) { - THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); - } - _current = _json.get(); - return; - } -#endif - - // not found - setToNull(); -} diff --git a/arangod/VocBase/DocumentAccessor.h b/arangod/VocBase/DocumentAccessor.h deleted file mode 100644 index 6580a9c487..0000000000 --- a/arangod/VocBase/DocumentAccessor.h +++ /dev/null @@ -1,125 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// DISCLAIMER -/// -/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany -/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// -/// Copyright holder is ArangoDB GmbH, Cologne, Germany -/// -/// @author Jan Steemann -//////////////////////////////////////////////////////////////////////////////// - -#ifndef ARANGOD_VOC_BASE_DOCUMENT_ACCESSOR_H -#define ARANGOD_VOC_BASE_DOCUMENT_ACCESSOR_H 1 - -#include "Basics/Common.h" -#include "Basics/JsonHelper.h" -#include "Utils/Transaction.h" -#include "VocBase/document-collection.h" -#include "Wal/Marker.h" - -#include -#include -#include - -struct TRI_doc_mptr_t; - -namespace arangodb { -class CollectionNameResolver; -} - -class DocumentAccessor { - public: - DocumentAccessor(DocumentAccessor const&); - DocumentAccessor& operator=(DocumentAccessor const&); - - DocumentAccessor(arangodb::CollectionNameResolver const* resolver, - TRI_document_collection_t* document, - TRI_doc_mptr_t const* mptr); - - explicit DocumentAccessor(TRI_json_t const* json); - explicit DocumentAccessor(VPackSlice const& slice); - - ~DocumentAccessor(); - - public: - bool hasKey(std::string const& attribute) const; - - bool isObject() const; - - bool isArray() const; - - size_t length() const; - - DocumentAccessor& get(char const* name, size_t nameLength); - - DocumentAccessor& get(std::string const& name); - - DocumentAccessor& at(int64_t index); - - arangodb::basics::Json toJson(); - - private: - void setToNull(); - - void lookupJsonAttribute(char const* name, size_t nameLength); - - void lookupDocumentAttribute(char const* name, size_t nameLength); - - private: - arangodb::CollectionNameResolver const* _resolver; - - TRI_document_collection_t* _document; - - TRI_doc_mptr_t const* _mptr; - - std::unique_ptr _json; // the JSON that we own - - TRI_json_t const* _current; // the JSON that we point to -}; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief extracts the key from a marker -//////////////////////////////////////////////////////////////////////////////// - -static inline std::string TRI_EXTRACT_MARKER_KEY( - arangodb::Transaction* trx, TRI_df_marker_t const* marker) { -#if 0 - if (marker->_type == TRI_DF_MARKER_VPACK_DOCUMENT) { - auto b = reinterpret_cast(marker) + - sizeof(arangodb::wal::vpack_document_marker_t); - VPackSlice slice(reinterpret_cast(b)); - return slice.get(TRI_VOC_ATTRIBUTE_KEY).copyString(); - } - -#ifdef ARANGODB_ENABLE_MAINTAINER_MODE - // invalid marker type - TRI_ASSERT(false); -#endif -#endif - return ""; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief extracts the key from a marker -//////////////////////////////////////////////////////////////////////////////// - -static inline std::string TRI_EXTRACT_MARKER_KEY(arangodb::Transaction* trx, - TRI_doc_mptr_t const* mptr) { - return TRI_EXTRACT_MARKER_KEY( - trx, static_cast(mptr->getDataPtr())); -} - -#endif diff --git a/arangod/VocBase/Traverser.cpp b/arangod/VocBase/Traverser.cpp index ba157261bf..5315d71c14 100644 --- a/arangod/VocBase/Traverser.cpp +++ b/arangod/VocBase/Traverser.cpp @@ -25,6 +25,8 @@ #include "Basics/VelocyPackHelper.h" #include "Basics/json-utilities.h" #include "Indexes/EdgeIndex.h" +#include "Utils/Transaction.h" +#include "Utils/TransactionContext.h" #include "VocBase/KeyGenerator.h" using TraverserExpression = arangodb::traverser::TraverserExpression; @@ -150,15 +152,15 @@ TraverserExpression::TraverserExpression(VPackSlice const& slice) { basics::VelocyPackHelper::velocyPackToJson(slice.get("varAccess")), arangodb::basics::Json::AUTOFREE); - compareTo.reset(new arangodb::basics::Json( - TRI_UNKNOWN_MEM_ZONE, - basics::VelocyPackHelper::velocyPackToJson(slice.get("compareTo")), - arangodb::basics::Json::AUTOFREE)); - - if (compareTo->json() == nullptr) { - THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, - "invalid compareTo value"); + VPackSlice compareToSlice = slice.get("compareTo"); + VPackBuilder* builder = new VPackBuilder; + try { + builder->add(compareToSlice); + } catch (...) { + delete builder; + throw; } + compareTo.reset(builder); // If this fails everything before does not leak varAccess = new aql::AstNode(registerNode, registerString, varNode); } @@ -170,13 +172,17 @@ TraverserExpression::TraverserExpression(VPackSlice const& slice) { void TraverserExpression::toJson(arangodb::basics::Json& json, TRI_memory_zone_t* zone) const { json("isEdgeAccess", arangodb::basics::Json(isEdgeAccess))( - "comparisonType", - arangodb::basics::Json(static_cast(comparisonType)))( - "varAccess", varAccess->toJson(zone, true)); + "comparisonType", + arangodb::basics::Json(static_cast(comparisonType)))( + "varAccess", varAccess->toJson(zone, true)); - if (compareTo.get() != nullptr) { + if (compareTo != nullptr) { // We have to copy compareTo. The json is greedy and steals it... - json("compareTo", compareTo->copy()); + TRI_json_t* extracted = arangodb::basics::VelocyPackHelper::velocyPackToJson(compareTo->slice()); + if (extracted == nullptr) { + THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); + } + json("compareTo", arangodb::basics::Json(TRI_UNKNOWN_MEM_ZONE, TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, extracted))); } } @@ -186,22 +192,20 @@ void TraverserExpression::toJson(arangodb::basics::Json& json, //////////////////////////////////////////////////////////////////////////////// bool TraverserExpression::recursiveCheck(arangodb::aql::AstNode const* node, - DocumentAccessor& accessor) const { + arangodb::velocypack::Slice& element) const { switch (node->type) { case arangodb::aql::NODE_TYPE_REFERENCE: // We are on the variable access return true; case arangodb::aql::NODE_TYPE_ATTRIBUTE_ACCESS: { - char const* attributeName = node->getStringValue(); - TRI_ASSERT(attributeName != nullptr); - std::string name(attributeName, node->getStringLength()); - if (!recursiveCheck(node->getMember(0), accessor)) { + std::string name(node->getString()); + if (!recursiveCheck(node->getMember(0), element)) { return false; } - if (!accessor.isObject() || !accessor.hasKey(name)) { + if (!element.isObject() || !element.hasKey(name)) { return false; } - accessor.get(name); + element = element.get(name); break; } case arangodb::aql::NODE_TYPE_INDEXED_ACCESS: { @@ -209,14 +213,14 @@ bool TraverserExpression::recursiveCheck(arangodb::aql::AstNode const* node, if (!index->isIntValue()) { return false; } - if (!recursiveCheck(node->getMember(0), accessor)) { + if (!recursiveCheck(node->getMember(0), element)) { return false; } auto idx = index->getIntValue(); - if (!accessor.isArray()) { + if (!element.isArray()) { return false; } - accessor.at(idx); + element = element.at(idx); break; } default: @@ -226,64 +230,41 @@ bool TraverserExpression::recursiveCheck(arangodb::aql::AstNode const* node, } //////////////////////////////////////////////////////////////////////////////// -/// @brief evalutes if an element matches the given expression +/// @brief evaluates if an element matches the given expression //////////////////////////////////////////////////////////////////////////////// -bool TraverserExpression::matchesCheck(DocumentAccessor& accessor) const { - arangodb::basics::Json result(arangodb::basics::Json::Null); - if (recursiveCheck(varAccess, accessor)) { - result = accessor.toJson(); +bool TraverserExpression::matchesCheck(arangodb::Transaction* trx, + VPackSlice const& element) const { + TRI_ASSERT(trx != nullptr); + + VPackSlice value = element; + + // initialize compare value to Null + VPackSlice result = arangodb::basics::VelocyPackHelper::NullValue(); + // perform recursive check. this may modify value + if (recursiveCheck(varAccess, value)) { + result = element; } TRI_ASSERT(compareTo != nullptr); - TRI_ASSERT(compareTo->json() != nullptr); + VPackOptions* options = trx->transactionContext()->getVPackOptions(); switch (comparisonType) { case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_EQ: - return TRI_CompareValuesJson(result.json(), compareTo->json(), false) == - 0; + return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), false, options) == 0; case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_NE: - return TRI_CompareValuesJson(result.json(), compareTo->json(), false) != - 0; + return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), false, options) != 0; case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_LT: - return TRI_CompareValuesJson(result.json(), compareTo->json(), true) < 0; + return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) < 0; case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_LE: - return TRI_CompareValuesJson(result.json(), compareTo->json(), true) <= 0; + return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) <= 0; case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_GE: - return TRI_CompareValuesJson(result.json(), compareTo->json(), true) >= 0; + return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) >= 0; case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_GT: - return TRI_CompareValuesJson(result.json(), compareTo->json(), true) > 0; + return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) > 0; default: TRI_ASSERT(false); } return false; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief evalutes if an element matches the given expression -//////////////////////////////////////////////////////////////////////////////// - -bool TraverserExpression::matchesCheck(TRI_json_t const* element) const { - DocumentAccessor accessor(element); - return matchesCheck(accessor); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief evalutes if an element matches the given expression -//////////////////////////////////////////////////////////////////////////////// - -bool TraverserExpression::matchesCheck(VPackSlice const& element) const { - DocumentAccessor accessor(element); - return matchesCheck(accessor); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief evalutes if an element matches the given expression -//////////////////////////////////////////////////////////////////////////////// - -bool TraverserExpression::matchesCheck( - TRI_doc_mptr_t& element, TRI_document_collection_t* collection, - arangodb::CollectionNameResolver const* resolver) const { - DocumentAccessor accessor(resolver, collection, &element); - return matchesCheck(accessor); -} diff --git a/arangod/VocBase/Traverser.h b/arangod/VocBase/Traverser.h index 93217ac674..eadc5dd9b2 100644 --- a/arangod/VocBase/Traverser.h +++ b/arangod/VocBase/Traverser.h @@ -29,11 +29,13 @@ #include "Aql/AstNode.h" #include "Utils/CollectionNameResolver.h" #include "Utils/Transaction.h" -#include "VocBase/DocumentAccessor.h" #include "VocBase/voc-types.h" namespace arangodb { +class TransactionContext; + namespace velocypack { +class Builder; class Slice; } namespace traverser { @@ -80,7 +82,7 @@ class TraverserExpression { bool isEdgeAccess; arangodb::aql::AstNodeType comparisonType; arangodb::aql::AstNode const* varAccess; - std::unique_ptr compareTo; + std::unique_ptr compareTo; TraverserExpression(bool pisEdgeAccess, arangodb::aql::AstNodeType pcomparisonType, @@ -103,15 +105,7 @@ class TraverserExpression { void toJson(arangodb::basics::Json& json, TRI_memory_zone_t* zone) const; - bool matchesCheck(TRI_doc_mptr_t& element, - TRI_document_collection_t* collection, - CollectionNameResolver const* resolver) const; - - bool matchesCheck(TRI_json_t const* element) const; - - bool matchesCheck(arangodb::velocypack::Slice const& element) const; - - bool matchesCheck(DocumentAccessor& accessor) const; + bool matchesCheck(arangodb::Transaction*, arangodb::velocypack::Slice const& element) const; protected: TraverserExpression() @@ -121,7 +115,7 @@ class TraverserExpression { compareTo(nullptr) {} private: - bool recursiveCheck(arangodb::aql::AstNode const*, DocumentAccessor&) const; + bool recursiveCheck(arangodb::aql::AstNode const*, arangodb::velocypack::Slice&) const; // Required when creating this expression without AST std::vector> _nodeRegister;