mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'spdvpk' of ssh://github.com/ArangoDB/ArangoDB into spdvpk
This commit is contained in:
commit
5b807d6753
|
@ -33,6 +33,7 @@
|
|||
#include "VocBase/collection.h"
|
||||
|
||||
#include <velocypack/Iterator.h>
|
||||
#include <velocypack/Slice.h>
|
||||
#include <velocypack/velocypack-aliases.h>
|
||||
|
||||
using namespace arangodb::aql;
|
||||
|
@ -1046,25 +1047,22 @@ AstNode* Ast::createNodeIntersectedArray(AstNode const* lhs,
|
|||
size_t const nl = lhs->numMembers();
|
||||
size_t const nr = rhs->numMembers();
|
||||
|
||||
std::unordered_map<TRI_json_t*, AstNode const*, arangodb::basics::JsonHash,
|
||||
arangodb::basics::JsonEqual>
|
||||
cache(nl + nr, arangodb::basics::JsonHash(),
|
||||
arangodb::basics::JsonEqual());
|
||||
std::unordered_map<VPackSlice, AstNode const*> cache(nl + nr);
|
||||
|
||||
for (size_t i = 0; i < nl; ++i) {
|
||||
auto member = lhs->getMemberUnchecked(i);
|
||||
auto json = member->computeJson();
|
||||
VPackSlice slice = member->computeValue();
|
||||
|
||||
cache.emplace(json, member);
|
||||
cache.emplace(slice, member);
|
||||
}
|
||||
|
||||
auto node = createNodeArray();
|
||||
|
||||
for (size_t i = 0; i < nr; ++i) {
|
||||
auto member = rhs->getMemberUnchecked(i);
|
||||
auto json = member->computeJson();
|
||||
VPackSlice slice = member->computeValue();
|
||||
|
||||
auto it = cache.find(json);
|
||||
auto it = cache.find(slice);
|
||||
|
||||
if (it != cache.end()) {
|
||||
node->addMember((*it).second);
|
||||
|
@ -1085,10 +1083,7 @@ AstNode* Ast::createNodeUnionizedArray(AstNode const* lhs, AstNode const* rhs) {
|
|||
size_t const nl = lhs->numMembers();
|
||||
size_t const nr = rhs->numMembers();
|
||||
|
||||
std::unordered_map<TRI_json_t*, AstNode const*, arangodb::basics::JsonHash,
|
||||
arangodb::basics::JsonEqual>
|
||||
cache(nl + nr, arangodb::basics::JsonHash(),
|
||||
arangodb::basics::JsonEqual());
|
||||
std::unordered_map<VPackSlice, AstNode const*> cache(nl + nr);
|
||||
|
||||
for (size_t i = 0; i < nl + nr; ++i) {
|
||||
AstNode* member;
|
||||
|
@ -1097,9 +1092,9 @@ AstNode* Ast::createNodeUnionizedArray(AstNode const* lhs, AstNode const* rhs) {
|
|||
} else {
|
||||
member = rhs->getMemberUnchecked(i - nl);
|
||||
}
|
||||
auto json = member->computeJson();
|
||||
VPackSlice slice = member->computeValue();
|
||||
|
||||
cache.emplace(json, member);
|
||||
cache.emplace(slice, member);
|
||||
}
|
||||
|
||||
auto node = createNodeArray();
|
||||
|
@ -2039,16 +2034,14 @@ AstNode const* Ast::deduplicateArray(AstNode const* node) {
|
|||
|
||||
// TODO: sort values in place first and compare two adjacent members each
|
||||
|
||||
std::unordered_map<TRI_json_t*, AstNode const*, arangodb::basics::JsonHash,
|
||||
arangodb::basics::JsonEqual>
|
||||
cache(n, arangodb::basics::JsonHash(), arangodb::basics::JsonEqual());
|
||||
std::unordered_map<VPackSlice, AstNode const*> cache(n);
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
auto member = node->getMemberUnchecked(i);
|
||||
auto json = member->computeJson();
|
||||
VPackSlice slice = member->computeValue();
|
||||
|
||||
if (cache.find(json) == cache.end()) {
|
||||
cache.emplace(json, member);
|
||||
if (cache.find(slice) == cache.end()) {
|
||||
cache.emplace(slice, member);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#endif
|
||||
|
||||
#include <velocypack/Builder.h>
|
||||
#include <velocypack/Slice.h>
|
||||
#include <velocypack/velocypack-aliases.h>
|
||||
#include <array>
|
||||
|
||||
|
@ -432,7 +433,7 @@ static bool IsEmptyString(char const* p, size_t length) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode::AstNode(AstNodeType type)
|
||||
: type(type), flags(0), computedJson(nullptr) {}
|
||||
: type(type), flags(0), computedValue(nullptr) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a node, with defining a value type
|
||||
|
@ -441,7 +442,7 @@ AstNode::AstNode(AstNodeType type)
|
|||
AstNode::AstNode(AstNodeType type, AstNodeValueType valueType) : AstNode(type) {
|
||||
value.type = valueType;
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -453,7 +454,7 @@ AstNode::AstNode(bool v, AstNodeValueType valueType)
|
|||
TRI_ASSERT(valueType == VALUE_TYPE_BOOL);
|
||||
value.value._bool = v;
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -465,7 +466,7 @@ AstNode::AstNode(int64_t v, AstNodeValueType valueType)
|
|||
TRI_ASSERT(valueType == VALUE_TYPE_INT);
|
||||
value.value._int = v;
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -477,7 +478,7 @@ AstNode::AstNode(char const* v, size_t length, AstNodeValueType valueType)
|
|||
TRI_ASSERT(valueType == VALUE_TYPE_STRING);
|
||||
setStringValue(v, length);
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -487,7 +488,7 @@ AstNode::AstNode(char const* v, size_t length, AstNodeValueType valueType)
|
|||
AstNode::AstNode(Ast* ast, arangodb::basics::Json const& json)
|
||||
: AstNode(getNodeTypeFromJson(json)) {
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
|
||||
auto query = ast->query();
|
||||
|
||||
|
@ -676,7 +677,7 @@ AstNode::AstNode(std::function<void(AstNode*)> registerNode,
|
|||
arangodb::basics::Json const& json)
|
||||
: AstNode(getNodeTypeFromJson(json)) {
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
|
||||
switch (type) {
|
||||
case NODE_TYPE_ATTRIBUTE_ACCESS: {
|
||||
|
@ -830,9 +831,8 @@ AstNode::AstNode(std::function<void(AstNode*)> registerNode,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode::~AstNode() {
|
||||
if (computedJson != nullptr) {
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, computedJson);
|
||||
computedJson = nullptr;
|
||||
if (computedValue != nullptr) {
|
||||
delete[] computedValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -936,21 +936,23 @@ void AstNode::dump(int level) const {
|
|||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compute the JSON for a constant value node
|
||||
/// the JSON is owned by the node and must not be freed by the caller
|
||||
/// @brief compute the value for a constant value node
|
||||
/// the value is owned by the node and must not be freed by the caller
|
||||
/// note that the return value might be NULL in case of OOM
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_json_t* AstNode::computeJson() const {
|
||||
VPackSlice AstNode::computeValue() const {
|
||||
TRI_ASSERT(isConstant());
|
||||
|
||||
if (computedJson == nullptr) {
|
||||
// note: the following may fail but we do not need to
|
||||
// check that here
|
||||
computedJson = toJsonValue(TRI_UNKNOWN_MEM_ZONE);
|
||||
if (computedValue == nullptr) {
|
||||
VPackBuilder builder;
|
||||
toVelocyPackValue(builder);
|
||||
|
||||
computedValue = new uint8_t[builder.size()];
|
||||
memcpy(computedValue, builder.data(), builder.size());
|
||||
}
|
||||
|
||||
return computedJson;
|
||||
return VPackSlice(computedValue);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include "Basics/json.h"
|
||||
#include "Basics/JsonHelper.h"
|
||||
|
||||
#include <velocypack/Slice.h>
|
||||
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
|
||||
|
@ -291,12 +293,12 @@ struct AstNode {
|
|||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compute the JSON for a constant value node
|
||||
/// the JSON is owned by the node and must not be freed by the caller
|
||||
/// @brief compute the value for a constant value node
|
||||
/// the value is owned by the node and must not be freed by the caller
|
||||
/// note that the return value might be NULL in case of OOM
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_json_t* computeJson() const;
|
||||
arangodb::velocypack::Slice computeValue() const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief sort the members of an (array) node
|
||||
|
@ -932,10 +934,10 @@ struct AstNode {
|
|||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief precomputed JSON value (used when executing expressions)
|
||||
/// @brief precomputed VPack value (used when executing expressions)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_json_t mutable* computedJson;
|
||||
uint8_t mutable* computedValue;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the node's sub nodes
|
||||
|
|
|
@ -104,7 +104,7 @@ Expression::~Expression() {
|
|||
switch (_type) {
|
||||
case JSON:
|
||||
TRI_ASSERT(_data != nullptr);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _data);
|
||||
delete[] _data;
|
||||
break;
|
||||
|
||||
case ATTRIBUTE: {
|
||||
|
@ -154,9 +154,7 @@ AqlValue$ Expression::execute(arangodb::AqlTransaction* trx,
|
|||
case JSON: {
|
||||
// TODO
|
||||
TRI_ASSERT(_data != nullptr);
|
||||
VPackBuilder builder;
|
||||
JsonHelper::toVelocyPack(_data, builder);
|
||||
return AqlValue$(builder);
|
||||
return AqlValue$(VPackSlice(_data), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
}
|
||||
|
||||
case SIMPLE: {
|
||||
|
@ -171,22 +169,8 @@ AqlValue$ Expression::execute(arangodb::AqlTransaction* trx,
|
|||
|
||||
case V8: {
|
||||
TRI_ASSERT(_func != nullptr);
|
||||
try {
|
||||
ISOLATE;
|
||||
return _func->execute(isolate, _ast->query(), trx, argv, startPos, vars,
|
||||
regs);
|
||||
} catch (arangodb::basics::Exception& ex) {
|
||||
if (_ast->query()->verboseErrors()) {
|
||||
ex.addToMessage(" while evaluating expression ");
|
||||
auto json = _node->toJson(TRI_UNKNOWN_MEM_ZONE, false);
|
||||
|
||||
if (json != nullptr) {
|
||||
ex.addToMessage(arangodb::basics::JsonHelper::toString(json));
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
ISOLATE;
|
||||
return _func->execute(isolate, _ast->query(), trx, argv, startPos, vars, regs);
|
||||
}
|
||||
|
||||
case UNPROCESSED: {
|
||||
|
@ -408,12 +392,11 @@ void Expression::buildExpression() {
|
|||
if (_type == JSON) {
|
||||
TRI_ASSERT(_data == nullptr);
|
||||
// generate a constant value
|
||||
_data = _node->toJsonValue(TRI_UNKNOWN_MEM_ZONE);
|
||||
VPackBuilder builder;
|
||||
_node->toVelocyPackValue(builder);
|
||||
|
||||
if (_data == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||
"invalid json in simple expression");
|
||||
}
|
||||
_data = new uint8_t[builder.size()];
|
||||
memcpy(_data, builder.data(), builder.size());
|
||||
} else if (_type == V8) {
|
||||
// generate a V8 expression
|
||||
_func = _executor->generateExpression(_node);
|
||||
|
@ -651,16 +634,7 @@ AqlValue$ Expression::executeSimpleExpressionArray(
|
|||
std::vector<Variable const*> const& vars,
|
||||
std::vector<RegisterId> const& regs) {
|
||||
if (node->isConstant()) {
|
||||
auto json = node->computeJson();
|
||||
|
||||
if (json == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
VPackBuilder builder;
|
||||
JsonHelper::toVelocyPack(json, builder);
|
||||
|
||||
return AqlValue$(builder);
|
||||
return AqlValue$(node->computeValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
}
|
||||
|
||||
size_t const n = node->numMembers();
|
||||
|
@ -689,16 +663,7 @@ AqlValue$ Expression::executeSimpleExpressionObject(
|
|||
std::vector<Variable const*> const& vars,
|
||||
std::vector<RegisterId> const& regs) {
|
||||
if (node->isConstant()) {
|
||||
auto json = node->computeJson();
|
||||
|
||||
if (json == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
VPackBuilder builder;
|
||||
JsonHelper::toVelocyPack(json, builder);
|
||||
|
||||
return AqlValue$(builder);
|
||||
return AqlValue$(node->computeValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
}
|
||||
|
||||
VPackBuilder builder;
|
||||
|
@ -725,15 +690,7 @@ AqlValue$ Expression::executeSimpleExpressionObject(
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue$ Expression::executeSimpleExpressionValue(AstNode const* node) {
|
||||
auto json = node->computeJson();
|
||||
|
||||
if (json == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
VPackBuilder builder;
|
||||
JsonHelper::toVelocyPack(json, builder);
|
||||
return AqlValue$(builder);
|
||||
return AqlValue$(node->computeValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1270,14 +1227,14 @@ AqlValue$ Expression::executeSimpleExpressionArithmetic(
|
|||
trx, argv, startPos, vars, regs, true);
|
||||
|
||||
if (lhs.isObject()) {
|
||||
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
return AqlValue$(VelocyPackHelper::NullValue());
|
||||
}
|
||||
|
||||
AqlValue$ rhs = executeSimpleExpression(node->getMember(1),
|
||||
trx, argv, startPos, vars, regs, true);
|
||||
|
||||
if (rhs.isObject()) {
|
||||
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
return AqlValue$(VelocyPackHelper::NullValue());
|
||||
}
|
||||
|
||||
double const l = lhs.toDouble();
|
||||
|
@ -1298,17 +1255,17 @@ AqlValue$ Expression::executeSimpleExpressionArithmetic(
|
|||
case NODE_TYPE_OPERATOR_BINARY_DIV:
|
||||
if (r == 0.0) {
|
||||
RegisterWarning(_ast, "/", TRI_ERROR_QUERY_DIVISION_BY_ZERO);
|
||||
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
return AqlValue$(VelocyPackHelper::NullValue());
|
||||
}
|
||||
return AqlValue$(builder);
|
||||
case NODE_TYPE_OPERATOR_BINARY_MOD:
|
||||
if (r == 0.0) {
|
||||
RegisterWarning(_ast, "/", TRI_ERROR_QUERY_DIVISION_BY_ZERO);
|
||||
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
return AqlValue$(VelocyPackHelper::NullValue());
|
||||
}
|
||||
builder.add(VPackValue(fmod(l, r)));
|
||||
return AqlValue$(builder);
|
||||
default:
|
||||
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
return AqlValue$(VelocyPackHelper::NullValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -490,7 +490,7 @@ class Expression {
|
|||
union {
|
||||
V8Expression* _func;
|
||||
|
||||
struct TRI_json_t* _data;
|
||||
uint8_t* _data;
|
||||
|
||||
AttributeAccessor* _accessor;
|
||||
};
|
||||
|
|
|
@ -36,9 +36,11 @@
|
|||
#include "FulltextIndex/fulltext-result.h"
|
||||
#include "FulltextIndex/fulltext-query.h"
|
||||
#include "Indexes/Index.h"
|
||||
#include "Indexes/EdgeIndex.h"
|
||||
#include "Indexes/FulltextIndex.h"
|
||||
#include "Indexes/GeoIndex2.h"
|
||||
#include "Rest/SslInterface.h"
|
||||
#include "Utils/OperationCursor.h"
|
||||
#include "Utils/OperationOptions.h"
|
||||
#include "Utils/OperationResult.h"
|
||||
#include "Utils/Transaction.h"
|
||||
|
@ -64,6 +66,15 @@ using VertexId = arangodb::traverser::VertexId;
|
|||
thread_local std::unordered_map<std::string, RegexMatcher*>* RegexCache =
|
||||
nullptr;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Insert a mptr into the result
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void InsertMasterPointer(TRI_doc_mptr_t const* mptr, VPackBuilder& builder) {
|
||||
builder.add(VPackValue(static_cast<void const*>(mptr->vpack()),
|
||||
VPackValueType::External));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clear the regex cache in a thread
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -434,121 +445,10 @@ static bool SortNumberList(VPackSlice const& values,
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline void ExpandShapedJson(
|
||||
VocShaper* shaper, CollectionNameResolver const* resolver,
|
||||
TRI_voc_cid_t const& cid, TRI_doc_mptr_t const* mptr, VPackBuilder& b,
|
||||
bool keepTopLevelOpen,
|
||||
std::unordered_set<std::string> const& forbidden) {
|
||||
b.add(VPackValue(VPackValueType::Object));
|
||||
|
||||
TRI_df_marker_t const* marker =
|
||||
static_cast<TRI_df_marker_t const*>(mptr->getDataPtr());
|
||||
|
||||
TRI_shaped_json_t shaped;
|
||||
TRI_EXTRACT_SHAPED_JSON_MARKER(shaped, marker);
|
||||
std::shared_ptr<VPackBuilder> tmp = TRI_VelocyPackShapedJson(shaper, &shaped);
|
||||
// Copy the shaped into our local builder
|
||||
for (auto const& it : VPackObjectIterator(tmp->slice())) {
|
||||
std::string key = it.key.copyString();
|
||||
if (forbidden.count(key) == 0) {
|
||||
b.add(it.key.copyString(), it.value);
|
||||
}
|
||||
}
|
||||
|
||||
char const* key = TRI_EXTRACT_MARKER_KEY(marker);
|
||||
std::string id(resolver->getCollectionName(cid));
|
||||
id.push_back('/');
|
||||
id.append(key);
|
||||
if (forbidden.count(TRI_VOC_ATTRIBUTE_ID) == 0) {
|
||||
b.add(TRI_VOC_ATTRIBUTE_ID, VPackValue(id));
|
||||
}
|
||||
if (forbidden.count(TRI_VOC_ATTRIBUTE_REV) == 0) {
|
||||
b.add(TRI_VOC_ATTRIBUTE_REV,
|
||||
VPackValue(std::to_string(TRI_EXTRACT_MARKER_RID(marker))));
|
||||
}
|
||||
if (forbidden.count(TRI_VOC_ATTRIBUTE_KEY) == 0) {
|
||||
b.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(key));
|
||||
}
|
||||
|
||||
#if 0
|
||||
// TODO
|
||||
if (TRI_IS_EDGE_MARKER(marker)) {
|
||||
if (forbidden.count(TRI_VOC_ATTRIBUTE_FROM) == 0) {
|
||||
std::string from(resolver->getCollectionNameCluster(
|
||||
TRI_EXTRACT_MARKER_FROM_CID(marker)));
|
||||
from.push_back('/');
|
||||
from.append(TRI_EXTRACT_MARKER_FROM_KEY(marker));
|
||||
b.add(TRI_VOC_ATTRIBUTE_FROM, VPackValue(from));
|
||||
}
|
||||
|
||||
if (forbidden.count(TRI_VOC_ATTRIBUTE_TO) == 0) {
|
||||
std::string to(
|
||||
resolver->getCollectionNameCluster(TRI_EXTRACT_MARKER_TO_CID(marker)));
|
||||
|
||||
to.push_back('/');
|
||||
to.append(TRI_EXTRACT_MARKER_TO_KEY(marker));
|
||||
b.add(TRI_VOC_ATTRIBUTE_TO, VPackValue(to));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!keepTopLevelOpen) {
|
||||
b.close();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Reads a document by cid and key
|
||||
/// Also lazy locks the collection.
|
||||
/// Returns null if the document does not exist
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ReadDocument(arangodb::AqlTransaction* trx,
|
||||
CollectionNameResolver const* resolver,
|
||||
TRI_voc_cid_t cid, char const* key,
|
||||
VPackBuilder& result) {
|
||||
trx->addCollectionAtRuntime(cid);
|
||||
|
||||
OperationOptions options;
|
||||
|
||||
VPackSlice slice;
|
||||
#warning fill slice from key
|
||||
OperationResult opRes = trx->document(trx->collectionName(cid), slice, options);
|
||||
#warning fill mptr
|
||||
|
||||
if (opRes.code != TRI_ERROR_NO_ERROR) {
|
||||
result.add(VPackValue(VPackValueType::Null));
|
||||
} else {
|
||||
#warning convert opRes result to vpack external
|
||||
result.add(VPackValue(static_cast<void const*>(nullptr), VPackValueType::External));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief function to filter the given list of mptr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void FilterDocuments(arangodb::ExampleMatcher const* matcher,
|
||||
TRI_voc_cid_t cid,
|
||||
std::vector<TRI_doc_mptr_t>& toFilter) {
|
||||
if (matcher == nullptr) {
|
||||
return;
|
||||
}
|
||||
size_t resultCount = toFilter.size();
|
||||
for (size_t i = 0; i < resultCount; /* nothing */) {
|
||||
if (!matcher->matches(cid, &toFilter[i])) {
|
||||
toFilter.erase(toFilter.begin() + i);
|
||||
--resultCount;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RequestEdges(VPackSlice const& vertexSlice,
|
||||
arangodb::AqlTransaction* trx,
|
||||
CollectionNameResolver const* resolver,
|
||||
VocShaper* shaper, TRI_voc_cid_t cid,
|
||||
TRI_document_collection_t* collection,
|
||||
std::string const& collectionName,
|
||||
std::string const& indexId,
|
||||
TRI_edge_direction_e direction,
|
||||
arangodb::ExampleMatcher const* matcher,
|
||||
bool includeVertices, VPackBuilder& result) {
|
||||
|
@ -571,59 +471,109 @@ static void RequestEdges(VPackSlice const& vertexSlice,
|
|||
vertexId);
|
||||
}
|
||||
|
||||
TRI_voc_cid_t startCid = resolver->getCollectionIdLocal(parts[0]);
|
||||
if (startCid == 0) {
|
||||
if (trx->getCollectionType(parts[0]) == TRI_COL_TYPE_UNKNOWN) {
|
||||
THROW_ARANGO_EXCEPTION_FORMAT(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, "'%s'",
|
||||
parts[0].c_str());
|
||||
}
|
||||
|
||||
char* key = const_cast<char*>(parts[1].c_str());
|
||||
std::vector<TRI_doc_mptr_t> edges = TRI_LookupEdgesDocumentCollection(
|
||||
trx, collection, direction, startCid, key);
|
||||
FilterDocuments(matcher, cid, edges);
|
||||
size_t resultCount = edges.size();
|
||||
VPackBuilder searchValueBuilder;
|
||||
searchValueBuilder.openArray();
|
||||
switch (direction) {
|
||||
case TRI_EDGE_OUT:
|
||||
searchValueBuilder.openArray();
|
||||
searchValueBuilder.openObject();
|
||||
searchValueBuilder.add(TRI_SLICE_KEY_EQUAL, VPackValue(vertexId));
|
||||
searchValueBuilder.close();
|
||||
searchValueBuilder.close();
|
||||
searchValueBuilder.add(VPackValue(VPackValueType::None));
|
||||
break;
|
||||
case TRI_EDGE_IN:
|
||||
searchValueBuilder.add(VPackValue(VPackValueType::None));
|
||||
searchValueBuilder.openArray();
|
||||
searchValueBuilder.openObject();
|
||||
searchValueBuilder.add(TRI_SLICE_KEY_EQUAL, VPackValue(vertexId));
|
||||
searchValueBuilder.close();
|
||||
searchValueBuilder.close();
|
||||
break;
|
||||
case TRI_EDGE_ANY:
|
||||
searchValueBuilder.openArray();
|
||||
searchValueBuilder.openObject();
|
||||
searchValueBuilder.add(TRI_SLICE_KEY_EQUAL, VPackValue(vertexId));
|
||||
searchValueBuilder.close();
|
||||
searchValueBuilder.close();
|
||||
searchValueBuilder.openArray();
|
||||
searchValueBuilder.openObject();
|
||||
searchValueBuilder.add(TRI_SLICE_KEY_EQUAL, VPackValue(vertexId));
|
||||
searchValueBuilder.close();
|
||||
searchValueBuilder.close();
|
||||
}
|
||||
searchValueBuilder.close();
|
||||
VPackSlice search = searchValueBuilder.slice();
|
||||
OperationCursor cursor = trx->indexScan(
|
||||
collectionName, arangodb::Transaction::CursorType::INDEX, indexId,
|
||||
search, 0, UINT64_MAX, 1000, false);
|
||||
if (cursor.failed()) {
|
||||
THROW_ARANGO_EXCEPTION(cursor.code);
|
||||
}
|
||||
|
||||
if (includeVertices) {
|
||||
for (size_t i = 0; i < resultCount; ++i) {
|
||||
VPackObjectBuilder guard(&result);
|
||||
result.add(VPackValue("edge"));
|
||||
std::unordered_set<std::string> unused;
|
||||
#warning convert to vpack
|
||||
ExpandShapedJson(shaper, resolver, cid, &(edges[i]), result, false, unused);
|
||||
char const* targetKey = nullptr;
|
||||
TRI_voc_cid_t targetCid = 0;
|
||||
while (cursor.hasMore()) {
|
||||
cursor.getMore();
|
||||
VPackSlice edges = cursor.slice();
|
||||
TRI_ASSERT(edges.isArray());
|
||||
if (includeVertices) {
|
||||
for (auto const& edge : VPackArrayIterator(edges)) {
|
||||
VPackObjectBuilder guard(&result);
|
||||
if (matcher->matches(edge)) {
|
||||
result.add("edge", edge);
|
||||
|
||||
switch (direction) {
|
||||
case TRI_EDGE_OUT:
|
||||
targetKey = TRI_EXTRACT_MARKER_TO_KEY(&edges[i]);
|
||||
targetCid = TRI_EXTRACT_MARKER_TO_CID(&edges[i]);
|
||||
break;
|
||||
case TRI_EDGE_IN:
|
||||
targetKey = TRI_EXTRACT_MARKER_FROM_KEY(&edges[i]);
|
||||
targetCid = TRI_EXTRACT_MARKER_FROM_CID(&edges[i]);
|
||||
break;
|
||||
case TRI_EDGE_ANY:
|
||||
targetKey = TRI_EXTRACT_MARKER_TO_KEY(&edges[i]);
|
||||
targetCid = TRI_EXTRACT_MARKER_TO_CID(&edges[i]);
|
||||
if (targetCid == startCid && strcmp(targetKey, key) == 0) {
|
||||
targetKey = TRI_EXTRACT_MARKER_FROM_KEY(&edges[i]);
|
||||
targetCid = TRI_EXTRACT_MARKER_FROM_CID(&edges[i]);
|
||||
std::string target;
|
||||
TRI_ASSERT(edge.hasKey(TRI_VOC_ATTRIBUTE_FROM));
|
||||
TRI_ASSERT(edge.hasKey(TRI_VOC_ATTRIBUTE_TO));
|
||||
switch (direction) {
|
||||
case TRI_EDGE_OUT:
|
||||
target = edge.get(TRI_VOC_ATTRIBUTE_TO).copyString();
|
||||
break;
|
||||
case TRI_EDGE_IN:
|
||||
target = edge.get(TRI_VOC_ATTRIBUTE_FROM).copyString();
|
||||
break;
|
||||
case TRI_EDGE_ANY:
|
||||
target = edge.get(TRI_VOC_ATTRIBUTE_TO).copyString();
|
||||
if (target == vertexId) {
|
||||
target = edge.get(TRI_VOC_ATTRIBUTE_FROM).copyString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (targetKey == nullptr || targetCid == 0) {
|
||||
// somehow invalid
|
||||
continue;
|
||||
if (target.empty()) {
|
||||
// somehow invalid
|
||||
continue;
|
||||
}
|
||||
std::vector<std::string> split = arangodb::basics::StringUtils::split(target, "/");
|
||||
TRI_ASSERT(split.size() == 2);
|
||||
VPackBuilder vertexSearch;
|
||||
vertexSearch.openObject();
|
||||
vertexSearch.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(split[1]));
|
||||
vertexSearch.close();
|
||||
OperationOptions opts;
|
||||
OperationResult vertexResult = trx->document(split[0], vertexSearch.slice(), opts);
|
||||
if (vertexResult.failed()) {
|
||||
if (vertexResult.code == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) {
|
||||
// This is okay
|
||||
result.add("vertex", VPackValue(VPackValueType::Null));
|
||||
} else {
|
||||
THROW_ARANGO_EXCEPTION(vertexResult.code);
|
||||
}
|
||||
} else {
|
||||
result.add("vertex", vertexResult.slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto const& edge : VPackArrayIterator(edges)) {
|
||||
if (matcher->matches(edge)) {
|
||||
result.add(edge);
|
||||
}
|
||||
}
|
||||
|
||||
result.add(VPackValue("vertex"));
|
||||
ReadDocument(trx, resolver, targetCid, targetKey, result);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < resultCount; ++i) {
|
||||
#warning convert to vpack
|
||||
// ExpandShapedJson(shaper, resolver, cid, &(edges[i]), result, false, unused);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -655,6 +605,108 @@ static void UnsetOrKeep(VPackSlice const& value,
|
|||
}
|
||||
}
|
||||
|
||||
static void RegisterCollectionInTransaction(
|
||||
arangodb::AqlTransaction* trx, std::string const& collectionName,
|
||||
TRI_voc_cid_t& cid) {
|
||||
cid = trx->resolver()->getCollectionIdLocal(collectionName);
|
||||
|
||||
if (cid == 0) {
|
||||
THROW_ARANGO_EXCEPTION_FORMAT(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, "'%s'",
|
||||
collectionName.c_str());
|
||||
}
|
||||
trx->addCollectionAtRuntime(cid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Helper function to get a document by it's identifier
|
||||
/// Lazy Locks the collection if necessary.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void GetDocumentByIdentifier(arangodb::AqlTransaction* trx,
|
||||
std::string const& collectionName,
|
||||
std::string const& identifier,
|
||||
bool ignoreError,
|
||||
VPackBuilder& result) {
|
||||
OperationOptions options;
|
||||
OperationResult opRes;
|
||||
VPackBuilder searchBuilder;
|
||||
searchBuilder.openObject();
|
||||
searchBuilder.add(VPackValue(TRI_VOC_ATTRIBUTE_KEY));
|
||||
|
||||
std::vector<std::string> parts =
|
||||
arangodb::basics::StringUtils::split(identifier, "/");
|
||||
|
||||
|
||||
if (parts.size() == 1) {
|
||||
searchBuilder.add(VPackValue(identifier));
|
||||
searchBuilder.close();
|
||||
|
||||
try {
|
||||
TRI_voc_cid_t cid;
|
||||
RegisterCollectionInTransaction(trx, collectionName, cid);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
opRes = trx->document(collectionName, searchBuilder.slice(), options);
|
||||
} else if (parts.size() == 2) {
|
||||
if (collectionName.empty()) {
|
||||
searchBuilder.add(VPackValue(parts[1]));
|
||||
searchBuilder.close();
|
||||
|
||||
try {
|
||||
TRI_voc_cid_t cid;
|
||||
RegisterCollectionInTransaction(trx, parts[0], cid);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
opRes = trx->document(parts[0], searchBuilder.slice(), options);
|
||||
} else if (parts[0] != collectionName) {
|
||||
// Reqesting an _id that cannot be stored in this collection
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_CROSS_COLLECTION_REQUEST);
|
||||
} else {
|
||||
searchBuilder.add(VPackValue(parts[1]));
|
||||
searchBuilder.close();
|
||||
|
||||
try {
|
||||
TRI_voc_cid_t cid;
|
||||
RegisterCollectionInTransaction(trx, collectionName, cid);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
opRes = trx->document(collectionName, searchBuilder.slice(), options);
|
||||
}
|
||||
} else {
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
|
||||
}
|
||||
if (opRes.failed()) {
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
THROW_ARANGO_EXCEPTION(opRes.code);
|
||||
}
|
||||
|
||||
result.add(opRes.slice());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Helper function to merge given parameters
|
||||
/// Works for an array of objects as first parameter or arbitrary many
|
||||
|
@ -732,63 +784,25 @@ static AqlValue$ MergeParameters(arangodb::aql::Query* query,
|
|||
return AqlValue$(b);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Transforms VertexId to VelocyPack
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void VertexIdToVPack(arangodb::AqlTransaction* trx,
|
||||
CollectionNameResolver const* resolver,
|
||||
VertexId const& id,
|
||||
VPackBuilder& b) {
|
||||
trx->addCollectionAtRuntime(id.cid);
|
||||
|
||||
OperationOptions options;
|
||||
|
||||
VPackSlice slice;
|
||||
#warning fill slice from id.key
|
||||
OperationResult opRes = trx->document(trx->collectionName(id.cid), slice, options);
|
||||
#warning fill mptr
|
||||
int res = opRes.code;
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
if (res == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) {
|
||||
b.add(VPackValue(VPackValueType::Null));
|
||||
return;
|
||||
}
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
|
||||
#warning convert to vpack
|
||||
b.add(VPackValue(static_cast<void const*>(nullptr), VPackValueType::External));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Transforms VertexId to std::string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::string VertexIdToString(CollectionNameResolver const* resolver,
|
||||
VertexId const& id) {
|
||||
return resolver->getCollectionName(id.cid) + "/" + std::string(id.key);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Transforms an unordered_map<VertexId> to AQL VelocyPack values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static AqlValue$ VertexIdsToAqlValueVPack(
|
||||
arangodb::aql::Query* query, arangodb::AqlTransaction* trx,
|
||||
CollectionNameResolver const* resolver, std::unordered_set<VertexId>& ids,
|
||||
bool includeData = false) {
|
||||
static AqlValue$ VertexIdsToAqlValueVPack(arangodb::aql::Query* query,
|
||||
arangodb::AqlTransaction* trx,
|
||||
std::unordered_set<std::string>& ids,
|
||||
bool includeData = false) {
|
||||
std::shared_ptr<VPackBuilder> result = query->getSharedBuilder();
|
||||
{
|
||||
VPackArrayBuilder b(result.get());
|
||||
if (includeData) {
|
||||
for (auto& it : ids) {
|
||||
VertexIdToVPack(trx, resolver, it, *result);
|
||||
// THROWS ERRORS if the Document was not found
|
||||
GetDocumentByIdentifier(trx, "", it, false, *result);
|
||||
}
|
||||
} else {
|
||||
for (auto& it : ids) {
|
||||
result->add(VPackValue(VertexIdToString(resolver, it)));
|
||||
result->add(VPackValue(it));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -832,12 +846,9 @@ static arangodb::Index* getGeoIndex(arangodb::AqlTransaction* trx,
|
|||
}
|
||||
|
||||
static AqlValue$ buildGeoResult(arangodb::aql::Query* query,
|
||||
GeoCoordinates* cors, VocShaper* shaper,
|
||||
CollectionNameResolver const* resolver,
|
||||
GeoCoordinates* cors,
|
||||
TRI_voc_cid_t const& cid,
|
||||
std::string const& attributeName) {
|
||||
// TODO FIXME
|
||||
// note: shaper will always be nullptr here...
|
||||
if (cors == nullptr) {
|
||||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||
{
|
||||
|
@ -892,19 +903,22 @@ static AqlValue$ buildGeoResult(arangodb::aql::Query* query,
|
|||
try {
|
||||
VPackArrayBuilder guard(b.get());
|
||||
std::unordered_set<std::string> forbidden;
|
||||
bool saveAttr = !attributeName.empty();
|
||||
if (saveAttr) {
|
||||
forbidden.emplace(attributeName);
|
||||
}
|
||||
|
||||
for (auto& it : distances) {
|
||||
#warning convert to vpack
|
||||
ExpandShapedJson(shaper, resolver, cid, it._mptr, *b,
|
||||
saveAttr, forbidden);
|
||||
if (saveAttr) {
|
||||
// The Object is Open and attributeName is not set
|
||||
if (!attributeName.empty()) {
|
||||
// We have to copy the entire document
|
||||
for (auto& it : distances) {
|
||||
VPackObjectBuilder docGuard(b.get());
|
||||
b->add(attributeName, VPackValue(it._distance));
|
||||
b->close();
|
||||
VPackSlice doc(it._mptr->vpack());
|
||||
for (auto const& entry : VPackObjectIterator(doc)) {
|
||||
std::string key = entry.key.copyString();
|
||||
if (key != attributeName) {
|
||||
b->add(key, entry.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto& it : distances) {
|
||||
InsertMasterPointer(it._mptr, *b);
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
|
@ -2332,7 +2346,7 @@ AqlValue$ Functions::Neighbors(arangodb::aql::Query* query,
|
|||
if (n > 4) {
|
||||
auto edgeExamples = ExtractFunctionParameter(trx, parameters, 4);
|
||||
if (!(edgeExamples.isArray() && edgeExamples.length() == 0)) {
|
||||
opts.addEdgeFilter(edgeExamples, eci->getShaper(), eCid, resolver);
|
||||
opts.addEdgeFilter(edgeExamples, eCid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2349,10 +2363,10 @@ AqlValue$ Functions::Neighbors(arangodb::aql::Query* query,
|
|||
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
|
||||
}
|
||||
|
||||
std::unordered_set<VertexId> neighbors;
|
||||
TRI_RunNeighborsSearch(edgeCollectionInfos, opts, neighbors);
|
||||
std::unordered_set<std::string> neighbors;
|
||||
#warning TRI_RunNeighborsSearch(edgeCollectionInfos, opts, neighbors);
|
||||
|
||||
return VertexIdsToAqlValueVPack(query, trx, resolver, neighbors, includeData);
|
||||
return VertexIdsToAqlValueVPack(query, trx, neighbors, includeData);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2426,7 +2440,7 @@ AqlValue$ Functions::Near(arangodb::aql::Query* query,
|
|||
trx, latitude.getNumericValue<double>(),
|
||||
longitude.getNumericValue<double>(), limitValue);
|
||||
|
||||
return buildGeoResult(query, cors, nullptr, resolver, cid, attributeName);
|
||||
return buildGeoResult(query, cors, cid, attributeName);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2488,7 +2502,7 @@ AqlValue$ Functions::Within(arangodb::aql::Query* query,
|
|||
trx, latitude.getNumericValue<double>(),
|
||||
longitude.getNumericValue<double>(), radius.getNumericValue<double>());
|
||||
|
||||
return buildGeoResult(query, cors, nullptr, resolver, cid, attributeName);
|
||||
return buildGeoResult(query, cors, cid, attributeName);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2693,104 +2707,6 @@ AqlValue$ Functions::Minus(arangodb::aql::Query* query,
|
|||
return AqlValue$(b.get());
|
||||
}
|
||||
|
||||
static void RegisterCollectionInTransaction(
|
||||
arangodb::AqlTransaction* trx, std::string const& collectionName,
|
||||
TRI_voc_cid_t& cid) {
|
||||
cid = trx->resolver()->getCollectionIdLocal(collectionName);
|
||||
|
||||
if (cid == 0) {
|
||||
THROW_ARANGO_EXCEPTION_FORMAT(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, "'%s'",
|
||||
collectionName.c_str());
|
||||
}
|
||||
|
||||
trx->addCollectionAtRuntime(cid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Helper function to get a document by it's identifier
|
||||
/// The collection has to be locked by the transaction before
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void GetDocumentByIdentifier(arangodb::AqlTransaction* trx,
|
||||
std::string const& collectionName,
|
||||
std::string const& identifier,
|
||||
VPackBuilder& result) {
|
||||
OperationOptions options;
|
||||
|
||||
std::vector<std::string> parts =
|
||||
arangodb::basics::StringUtils::split(identifier, "/");
|
||||
|
||||
if (parts.size() == 1) {
|
||||
VPackSlice slice;
|
||||
#warning fill slice from parts[0]
|
||||
OperationResult opRes = trx->document(collectionName, slice, options);
|
||||
#warning fill mptr
|
||||
if (!opRes.successful()) {
|
||||
return;
|
||||
}
|
||||
} else if (parts.size() == 2) {
|
||||
if (parts[0] != collectionName) {
|
||||
// Reqesting an _id that cannot be stored in this collection
|
||||
return;
|
||||
}
|
||||
VPackSlice slice;
|
||||
#warning fill slice from parts[1]
|
||||
OperationResult opRes = trx->document(collectionName, slice, options);
|
||||
#warning fill mptr
|
||||
if (!opRes.successful()) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
#warning convert to vpack
|
||||
result.add(VPackValue(static_cast<void const*>(nullptr), VPackValueType::External));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Helper function to get a document by its _id
|
||||
/// This function will lazy read-lock the collection.
|
||||
/// this function will not throw if the document or the collection cannot be
|
||||
/// found
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void GetDocumentByIdentifier(arangodb::AqlTransaction* trx,
|
||||
std::string const& identifier,
|
||||
VPackBuilder& result) {
|
||||
std::vector<std::string> parts =
|
||||
arangodb::basics::StringUtils::split(identifier, "/");
|
||||
|
||||
if (parts.size() != 2) {
|
||||
return;
|
||||
}
|
||||
std::string collectionName = parts[0];
|
||||
TRI_voc_cid_t cid = 0;
|
||||
try {
|
||||
RegisterCollectionInTransaction(trx, collectionName, cid);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
// don't throw if collection is not found
|
||||
if (ex.code() == TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
|
||||
return;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
OperationOptions options;
|
||||
|
||||
VPackSlice slice;
|
||||
#warning fill slice from parts[1]
|
||||
OperationResult opRes = trx->document(collectionName, slice, options);
|
||||
#warning fill mptr
|
||||
|
||||
if (opRes.code != TRI_ERROR_NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
#warning convert opRes result to vpack external
|
||||
result.add(VPackValue(static_cast<void const*>(nullptr), VPackValueType::External));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief function Document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2811,7 +2727,7 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
|||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||
if (id.isString()) {
|
||||
std::string identifier = id.copyString();
|
||||
GetDocumentByIdentifier(trx, identifier, *b);
|
||||
GetDocumentByIdentifier(trx, "", identifier, true, *b);
|
||||
if (b->isEmpty()) {
|
||||
// not found
|
||||
b->add(VPackValue(VPackValueType::Null));
|
||||
|
@ -2819,13 +2735,9 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
|||
} else if (id.isArray()) {
|
||||
VPackArrayBuilder guard(b.get());
|
||||
for (auto const& next : VPackArrayIterator(id)) {
|
||||
try {
|
||||
if (next.isString()) {
|
||||
std::string identifier = next.copyString();
|
||||
GetDocumentByIdentifier(trx, identifier, *b);
|
||||
}
|
||||
} catch (arangodb::basics::Exception const&) {
|
||||
// Ignore all ArangoDB exceptions here
|
||||
if (next.isString()) {
|
||||
std::string identifier = next.copyString();
|
||||
GetDocumentByIdentifier(trx, "", identifier, true, *b);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2840,19 +2752,8 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
|||
}
|
||||
std::string collectionName = collectionSlice.copyString();
|
||||
|
||||
TRI_voc_cid_t cid;
|
||||
bool notFound = false;
|
||||
|
||||
try {
|
||||
RegisterCollectionInTransaction(trx, collectionName, cid);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
// don't throw if collection is not found
|
||||
if (ex.code() != TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
|
||||
throw;
|
||||
}
|
||||
notFound = true;
|
||||
}
|
||||
|
||||
VPackSlice id = ExtractFunctionParameter(trx, parameters, 1);
|
||||
if (id.isString()) {
|
||||
if (notFound) {
|
||||
|
@ -2862,7 +2763,7 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
|||
}
|
||||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||
std::string identifier = id.copyString();
|
||||
GetDocumentByIdentifier(trx, collectionName, identifier, *b);
|
||||
GetDocumentByIdentifier(trx, collectionName, identifier, true, *b);
|
||||
if (b->isEmpty()) {
|
||||
b->add(VPackValue(VPackValueType::Null));
|
||||
}
|
||||
|
@ -2873,13 +2774,9 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
|||
VPackArrayBuilder guard(b.get());
|
||||
if (!notFound) {
|
||||
for (auto const& next : VPackArrayIterator(id)) {
|
||||
try {
|
||||
if (next.isString()) {
|
||||
std::string identifier = next.copyString();
|
||||
GetDocumentByIdentifier(trx, collectionName, identifier, *b);
|
||||
}
|
||||
} catch (arangodb::basics::Exception const&) {
|
||||
// Ignore all ArangoDB exceptions here
|
||||
if (next.isString()) {
|
||||
std::string identifier = next.copyString();
|
||||
GetDocumentByIdentifier(trx, collectionName, identifier, true, *b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2916,7 +2813,6 @@ AqlValue$ Functions::Edges(arangodb::aql::Query* query,
|
|||
TRI_voc_cid_t cid;
|
||||
RegisterCollectionInTransaction(trx, collectionName, cid);
|
||||
|
||||
TRI_document_collection_t* documentCollection = trx->documentCollection(cid);
|
||||
|
||||
if (!trx->isEdgeCollection(collectionName)) {
|
||||
RegisterWarning(query, "EDGES", TRI_ERROR_ARANGO_COLLECTION_TYPE_INVALID);
|
||||
|
@ -2964,18 +2860,20 @@ AqlValue$ Functions::Edges(arangodb::aql::Query* query,
|
|||
return AqlValue$(b.get());
|
||||
}
|
||||
|
||||
auto resolver = trx->resolver();
|
||||
|
||||
auto shaper = documentCollection->getShaper();
|
||||
std::unique_ptr<arangodb::ExampleMatcher> matcher;
|
||||
|
||||
TRI_document_collection_t* documentCollection = trx->documentCollection(cid);
|
||||
arangodb::EdgeIndex* edgeIndex = documentCollection->edgeIndex();
|
||||
TRI_ASSERT(edgeIndex != nullptr); // Checked because collection is edge Collection.
|
||||
std::string indexId = arangodb::basics::StringUtils::itoa(edgeIndex->id());
|
||||
|
||||
if (n > 3) {
|
||||
// We might have examples
|
||||
VPackSlice exampleSlice = ExtractFunctionParameter(trx, parameters, 3);
|
||||
if ((exampleSlice.isArray() && exampleSlice.length() != 0)|| exampleSlice.isObject()) {
|
||||
try {
|
||||
matcher.reset(
|
||||
new arangodb::ExampleMatcher(exampleSlice, resolver, false));
|
||||
new arangodb::ExampleMatcher(exampleSlice, false));
|
||||
} catch (arangodb::basics::Exception const& e) {
|
||||
if (e.code() != TRI_RESULT_ELEMENT_NOT_FOUND) {
|
||||
throw;
|
||||
|
@ -3008,16 +2906,14 @@ AqlValue$ Functions::Edges(arangodb::aql::Query* query,
|
|||
if (vertexSlice.isArray()) {
|
||||
for (auto const& v : VPackArrayIterator(vertexSlice)) {
|
||||
try {
|
||||
RequestEdges(v, trx, resolver, shaper, cid,
|
||||
documentCollection, direction,
|
||||
RequestEdges(v, trx, collectionName, indexId, direction,
|
||||
matcher.get(), includeVertices, *b);
|
||||
} catch (...) {
|
||||
// Errors in Array are simply ignored
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RequestEdges(vertexSlice, trx, resolver, shaper, cid,
|
||||
documentCollection, direction,
|
||||
RequestEdges(vertexSlice, trx, collectionName, indexId, direction,
|
||||
matcher.get(), includeVertices, *b);
|
||||
}
|
||||
}
|
||||
|
@ -4309,7 +4205,6 @@ AqlValue$ Functions::Fulltext(arangodb::aql::Query* query,
|
|||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
auto shaper = document->getShaper();
|
||||
size_t const numResults = queryResult->_numDocuments;
|
||||
|
||||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||
|
@ -4317,11 +4212,8 @@ AqlValue$ Functions::Fulltext(arangodb::aql::Query* query,
|
|||
VPackArrayBuilder guard(b.get());
|
||||
|
||||
for (size_t i = 0; i < numResults; ++i) {
|
||||
std::unordered_set<std::string> unused;
|
||||
#warning convert to vpack
|
||||
ExpandShapedJson(shaper, resolver, cid,
|
||||
(TRI_doc_mptr_t const*)queryResult->_documents[i], *b,
|
||||
false, unused);
|
||||
InsertMasterPointer((TRI_doc_mptr_t const*)queryResult->_documents[i],
|
||||
*b);
|
||||
}
|
||||
} catch (...) {
|
||||
TRI_FreeResultFulltextIndex(queryResult);
|
||||
|
|
|
@ -668,8 +668,7 @@ class PropagateConstantAttributesHelper {
|
|||
return;
|
||||
}
|
||||
|
||||
if (TRI_CompareValuesJson(value->computeJson(), previous->computeJson(),
|
||||
true) != 0) {
|
||||
if (!value->computeValue().equals(previous->computeValue())) {
|
||||
// different value found for an already tracked attribute. better not
|
||||
// use this attribute
|
||||
(*it2).second = nullptr;
|
||||
|
|
|
@ -241,6 +241,31 @@ void EdgeIndexIterator::reset() {
|
|||
_buffer = nullptr;
|
||||
}
|
||||
|
||||
TRI_doc_mptr_t* AnyDirectionEdgeIndexIterator::next() {
|
||||
TRI_doc_mptr_t* res = nullptr;
|
||||
if (_useInbound) {
|
||||
do {
|
||||
res = _inbound->next();
|
||||
} while (res != nullptr && _seen.find(res) != _seen.end());
|
||||
return res;
|
||||
}
|
||||
res = _outbound->next();
|
||||
if (res == nullptr) {
|
||||
_useInbound = true;
|
||||
return next();
|
||||
}
|
||||
_seen.emplace(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
void AnyDirectionEdgeIndexIterator::reset() {
|
||||
_useInbound = false;
|
||||
_seen.clear();
|
||||
_outbound->reset();
|
||||
_inbound->reset();
|
||||
}
|
||||
|
||||
|
||||
EdgeIndex::EdgeIndex(TRI_idx_iid_t iid, TRI_document_collection_t* collection)
|
||||
: Index(iid, collection,
|
||||
std::vector<std::vector<arangodb::basics::AttributeName>>(
|
||||
|
@ -529,6 +554,52 @@ arangodb::aql::AstNode* EdgeIndex::specializeCondition(
|
|||
return matcher.specializeOne(this, node, reference);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates an IndexIterator for the given VelocyPackSlices.
|
||||
/// The searchValue is a an Array with exactly two Entries.
|
||||
/// If the first is set it means we are searching for _from (OUTBOUND),
|
||||
/// if the second is set we are searching for _to (INBOUND).
|
||||
/// if both are set we are search for ANY direction. Result is made
|
||||
/// DISTINCT.
|
||||
/// Each defined slice that is set has to be list of keys to search for.
|
||||
/// Each key needs to have the following formats:
|
||||
///
|
||||
/// 1) {"eq": <compareValue>} // The value in index is exactly this
|
||||
///
|
||||
/// Reverse is not supported, hence ignored
|
||||
/// NOTE: The iterator is only valid as long as the slice points to
|
||||
/// a valid memory region.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IndexIterator* EdgeIndex::iteratorForSlice(
|
||||
arangodb::Transaction* trx, IndexIteratorContext*,
|
||||
arangodb::velocypack::Slice const searchValues, bool) const {
|
||||
if (!searchValues.isArray() || searchValues.length() != 2) {
|
||||
// Invalid searchValue
|
||||
return nullptr;
|
||||
}
|
||||
VPackSlice const from = searchValues.at(0);
|
||||
VPackSlice const to = searchValues.at(1);
|
||||
|
||||
if (!from.isNone()) {
|
||||
TRI_ASSERT(from.isArray());
|
||||
if (!to.isNone()) {
|
||||
// ANY search
|
||||
TRI_ASSERT(to.isArray());
|
||||
auto left = std::make_unique<EdgeIndexIterator>(trx, _edgesFrom, from);
|
||||
auto right = std::make_unique<EdgeIndexIterator>(trx, _edgesTo, to);
|
||||
return new AnyDirectionEdgeIndexIterator(left.release(), right.release());
|
||||
}
|
||||
// OUTBOUND search
|
||||
TRI_ASSERT(to.isNone());
|
||||
return new EdgeIndexIterator(trx, _edgesFrom, from);
|
||||
} else {
|
||||
// INBOUND search
|
||||
TRI_ASSERT(to.isArray());
|
||||
return new EdgeIndexIterator(trx, _edgesTo, to);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the iterator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -58,6 +58,20 @@ class EdgeIndexIterator final : public IndexIterator {
|
|||
_batchSize(50) { // This might be adjusted
|
||||
}
|
||||
|
||||
EdgeIndexIterator(arangodb::Transaction* trx,
|
||||
TRI_EdgeIndexHash_t const* index,
|
||||
arangodb::velocypack::Slice searchValues)
|
||||
: _trx(trx),
|
||||
_index(index),
|
||||
_searchValues(nullptr),
|
||||
_keys(searchValues),
|
||||
_position(0),
|
||||
_last(nullptr),
|
||||
_buffer(nullptr),
|
||||
_posInBuffer(0),
|
||||
_batchSize(50) { // This might be adjusted
|
||||
}
|
||||
|
||||
~EdgeIndexIterator() {
|
||||
// Free the vector space, not the content
|
||||
delete _buffer;
|
||||
|
@ -75,6 +89,32 @@ class EdgeIndexIterator final : public IndexIterator {
|
|||
size_t _batchSize;
|
||||
};
|
||||
|
||||
class AnyDirectionEdgeIndexIterator final : public IndexIterator {
|
||||
public:
|
||||
TRI_doc_mptr_t* next() override;
|
||||
|
||||
void reset() override;
|
||||
|
||||
AnyDirectionEdgeIndexIterator(EdgeIndexIterator* outboundIterator,
|
||||
EdgeIndexIterator* inboundIterator)
|
||||
: _outbound(outboundIterator),
|
||||
_inbound(inboundIterator),
|
||||
_useInbound(false),
|
||||
_done(false) {}
|
||||
|
||||
~AnyDirectionEdgeIndexIterator() {
|
||||
delete _outbound;
|
||||
delete _inbound;
|
||||
}
|
||||
|
||||
private:
|
||||
EdgeIndexIterator* _outbound;
|
||||
EdgeIndexIterator* _inbound;
|
||||
std::unordered_set<TRI_doc_mptr_t*> _seen;
|
||||
bool _useInbound;
|
||||
bool _done;
|
||||
};
|
||||
|
||||
class EdgeIndex final : public Index {
|
||||
public:
|
||||
EdgeIndex() = delete;
|
||||
|
@ -152,6 +192,26 @@ class EdgeIndex final : public Index {
|
|||
arangodb::aql::AstNode* specializeCondition(
|
||||
arangodb::aql::AstNode*, arangodb::aql::Variable const*) const override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates an IndexIterator for the given VelocyPackSlices.
|
||||
/// The searchValue is a an Array with exactly two Entries, one of them
|
||||
/// has to be NONE.
|
||||
/// If the first is set it means we are searching for _from (OUTBOUND),
|
||||
/// if the second is set we are searching for _to (INBOUND).
|
||||
/// The slice that is set has to be list of keys to search for.
|
||||
/// Each key needs to have the following formats:
|
||||
///
|
||||
/// 1) {"eq": <compareValue>} // The value in index is exactly this
|
||||
///
|
||||
/// Reverse is not supported, hence ignored
|
||||
/// NOTE: The iterator is only valid as long as the slice points to
|
||||
/// a valid memory region.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IndexIterator* iteratorForSlice(arangodb::Transaction*, IndexIteratorContext*,
|
||||
arangodb::velocypack::Slice const,
|
||||
bool) const override;
|
||||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the iterator
|
||||
|
|
|
@ -594,7 +594,7 @@ OperationResult Transaction::documentLocal(std::string const& collectionName,
|
|||
}
|
||||
|
||||
if (!options.silent) {
|
||||
resultBuilder.add(VPackSlice(mptr.vpack()));
|
||||
resultBuilder.add(VPackValue(static_cast<void const*>(mptr.vpack()), VPackValueType::External));
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
|
@ -1584,7 +1584,7 @@ OperationCursor Transaction::indexScan(
|
|||
std::string const& indexId, VPackSlice const search,
|
||||
uint64_t skip, uint64_t limit, uint64_t batchSize, bool reverse) {
|
||||
|
||||
// TODO Who checks if indexId is valid and is used for this collection?
|
||||
#warning TODO Who checks if indexId is valid and is used for this collection?
|
||||
// For now we assume indexId is the iid part of the index.
|
||||
|
||||
if (ServerState::instance()->isCoordinator()) {
|
||||
|
|
|
@ -248,13 +248,12 @@ bool BasicOptions::matchesVertex(VertexId const& v) const {
|
|||
// OperationResult opRes = trx->document(it->second.col, slice, options);
|
||||
OperationResult opRes(TRI_ERROR_INTERNAL);
|
||||
#warning fill vertex
|
||||
TRI_doc_mptr_t vertex;
|
||||
|
||||
if (!opRes.successful()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return it->second.matcher->matches(v.cid, &vertex);
|
||||
return it->second.matcher->matches(opRes.slice());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -302,13 +301,12 @@ void BasicOptions::addEdgeFilter(Json const& example, VocShaper* shaper,
|
|||
/// @brief Insert a new edge matcher object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void BasicOptions::addEdgeFilter(VPackSlice const& example, VocShaper* shaper,
|
||||
TRI_voc_cid_t const& cid,
|
||||
CollectionNameResolver const* resolver) {
|
||||
void BasicOptions::addEdgeFilter(VPackSlice const& example,
|
||||
TRI_voc_cid_t const& cid) {
|
||||
useEdgeFilter = true;
|
||||
auto it = _edgeFilter.find(cid);
|
||||
if (it == _edgeFilter.end()) {
|
||||
_edgeFilter.emplace(cid, new ExampleMatcher(example, resolver, true));
|
||||
_edgeFilter.emplace(cid, new ExampleMatcher(example, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,7 +330,7 @@ bool BasicOptions::matchesEdge(EdgeId& e, TRI_doc_mptr_t* edge) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
return it->second->matches(e.cid, edge);
|
||||
return it->second->matches(VPackSlice(edge->vpack()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -121,9 +121,8 @@ struct BasicOptions {
|
|||
TRI_voc_cid_t const& cid,
|
||||
arangodb::CollectionNameResolver const* resolver);
|
||||
|
||||
void addEdgeFilter(arangodb::velocypack::Slice const& example, VocShaper* shaper,
|
||||
TRI_voc_cid_t const& cid,
|
||||
arangodb::CollectionNameResolver const* resolver);
|
||||
void addEdgeFilter(arangodb::velocypack::Slice const& example,
|
||||
TRI_voc_cid_t const& cid);
|
||||
|
||||
void addVertexFilter(v8::Isolate* isolate,
|
||||
v8::Handle<v8::Value> const& example,
|
||||
|
|
|
@ -75,7 +75,7 @@ void ExampleMatcher::fillExampleDefinition(
|
|||
}
|
||||
|
||||
void ExampleMatcher::fillExampleDefinition(
|
||||
VPackSlice const& example, CollectionNameResolver const* resolver,
|
||||
VPackSlice const& example,
|
||||
ExampleDefinition& def) {
|
||||
TRI_ASSERT(def._values.isEmpty());
|
||||
VPackArrayBuilder guard(&def._values);
|
||||
|
@ -166,11 +166,10 @@ ExampleMatcher::ExampleMatcher(TRI_json_t const* example,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExampleMatcher::ExampleMatcher(VPackSlice const& example,
|
||||
CollectionNameResolver const* resolver,
|
||||
bool allowStrings) {
|
||||
if (example.isObject() || example.isString()) {
|
||||
ExampleDefinition def;
|
||||
ExampleMatcher::fillExampleDefinition(example, resolver, def);
|
||||
ExampleMatcher::fillExampleDefinition(example, def);
|
||||
definitions.emplace_back(std::move(def));
|
||||
} else if (example.isArray()) {
|
||||
for (auto const& e : VPackArrayIterator(example)) {
|
||||
|
@ -179,7 +178,7 @@ ExampleMatcher::ExampleMatcher(VPackSlice const& example,
|
|||
// We do not match strings in Array
|
||||
continue;
|
||||
}
|
||||
ExampleMatcher::fillExampleDefinition(e, resolver, def);
|
||||
ExampleMatcher::fillExampleDefinition(e, def);
|
||||
definitions.emplace_back(std::move(def));
|
||||
}
|
||||
if (definitions.empty()) {
|
||||
|
@ -190,16 +189,11 @@ ExampleMatcher::ExampleMatcher(VPackSlice const& example,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Checks if the given mptr matches the examples in this class
|
||||
/// @brief Checks if the given velocyPack matches the examples in this class
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ExampleMatcher::matches(TRI_voc_cid_t, TRI_doc_mptr_t const* mptr) const {
|
||||
if (mptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
VPackSlice toMatch(mptr->vpack());
|
||||
bool ExampleMatcher::matches(VPackSlice const toMatch) const {
|
||||
for (auto const& def : definitions) {
|
||||
VPackSlice const compareValue = def.slice();
|
||||
size_t i = 0;
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
|
||||
#include <v8.h>
|
||||
|
||||
struct TRI_doc_mptr_t;
|
||||
|
||||
namespace arangodb {
|
||||
|
||||
namespace velocypack {
|
||||
|
@ -50,7 +48,6 @@ class ExampleMatcher {
|
|||
std::vector<ExampleDefinition> definitions;
|
||||
|
||||
void fillExampleDefinition(arangodb::velocypack::Slice const& example,
|
||||
arangodb::CollectionNameResolver const* resolver,
|
||||
ExampleDefinition& def);
|
||||
|
||||
void fillExampleDefinition(v8::Isolate* isolate,
|
||||
|
@ -69,12 +66,11 @@ class ExampleMatcher {
|
|||
arangodb::CollectionNameResolver const* resolver);
|
||||
|
||||
ExampleMatcher(arangodb::velocypack::Slice const& example,
|
||||
arangodb::CollectionNameResolver const* resolver,
|
||||
bool allowStrings);
|
||||
|
||||
~ExampleMatcher() { }
|
||||
|
||||
bool matches(TRI_voc_cid_t, TRI_doc_mptr_t const* mptr) const;
|
||||
bool matches(arangodb::velocypack::Slice const) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue