mirror of https://gitee.com/bigwinds/arangodb
cppcheck fixes and dead code cleanup.
This commit is contained in:
parent
f4eeb1dbf0
commit
e8ff84c8da
|
@ -3657,54 +3657,6 @@ void arangodb::aql::optimizeTraversalsRule(Optimizer* opt,
|
|||
n->walk(&finder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now check if we can use an optimized version of the neighbors search...
|
||||
if (!arangodb::ServerState::instance()->isRunningInCluster()) {
|
||||
for (auto const& n : tNodes) {
|
||||
TraversalNode* traversal = static_cast<TraversalNode*>(n);
|
||||
|
||||
if (traversal->edgeOutVariable() != nullptr ||
|
||||
traversal->pathOutVariable() != nullptr) {
|
||||
// traversal produces edges or paths
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
if (!traversal->expressions()->empty()) {
|
||||
// traversal has filter expressions
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
if (!traversal->allDirectionsEqual()) {
|
||||
// not all directions are equal
|
||||
continue;
|
||||
}
|
||||
|
||||
traverser::TraverserOptions const* options = traversal->options();
|
||||
TRI_ASSERT(options != nullptr);
|
||||
|
||||
if (options->maxDepth > 100) {
|
||||
// neighbors search is recursive... do not use recursive version if
|
||||
// depth is potentially high
|
||||
continue;
|
||||
}
|
||||
|
||||
if (options->uniqueVertices != traverser::TraverserOptions::GLOBAL ||
|
||||
options->uniqueEdges != traverser::TraverserOptions::NONE) {
|
||||
// neighbors search is hard-coded to global vertex uniqueness
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!options->useBreadthFirst) {
|
||||
continue;
|
||||
}
|
||||
|
||||
traversal->specializeToNeighborsSearch();
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
opt->addPlan(plan, rule, modified);
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ ShortestPathNode::ShortestPathNode(ExecutionPlan* plan, size_t id,
|
|||
ShortestPathNode::ShortestPathNode(ExecutionPlan* plan, size_t id,
|
||||
TRI_vocbase_t* vocbase,
|
||||
std::vector<std::string> const& edgeColls,
|
||||
std::vector<TRI_edge_direction_e> directions,
|
||||
std::vector<TRI_edge_direction_e> const& directions,
|
||||
Variable const* inStartVariable,
|
||||
std::string const& startVertexId,
|
||||
Variable const* inTargetVariable,
|
||||
|
|
|
@ -54,7 +54,7 @@ class ShortestPathNode : public ExecutionNode {
|
|||
private:
|
||||
ShortestPathNode(ExecutionPlan* plan, size_t id, TRI_vocbase_t* vocbase,
|
||||
std::vector<std::string> const& edgeColls,
|
||||
std::vector<TRI_edge_direction_e> directions,
|
||||
std::vector<TRI_edge_direction_e> const& directions,
|
||||
Variable const* inStartVariable,
|
||||
std::string const& startVertexId,
|
||||
Variable const* inTargetVariable,
|
||||
|
|
|
@ -155,11 +155,6 @@ int TraversalBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
|||
bool TraversalBlock::morePaths(size_t hint) {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
|
||||
TraversalNode const* planNode = static_cast<TraversalNode const*>(getPlanNode());
|
||||
if (planNode->_specializedNeighborsSearch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
freeCaches();
|
||||
_posInPaths = 0;
|
||||
if (!_traverser->hasMore()) {
|
||||
|
@ -207,8 +202,6 @@ bool TraversalBlock::morePaths(size_t hint) {
|
|||
/// @brief skip the next paths
|
||||
size_t TraversalBlock::skipPaths(size_t hint) {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
TRI_ASSERT(!static_cast<TraversalNode const*>(getPlanNode())->_specializedNeighborsSearch);
|
||||
|
||||
freeCaches();
|
||||
_posInPaths = 0;
|
||||
if (!_traverser->hasMore()) {
|
||||
|
@ -237,8 +230,6 @@ void TraversalBlock::initializePaths(AqlItemBlock const* items, size_t pos) {
|
|||
return;
|
||||
}
|
||||
|
||||
TraversalNode const* planNode = static_cast<TraversalNode const*>(getPlanNode());
|
||||
|
||||
if (!_useRegister) {
|
||||
if (!_usedConstant) {
|
||||
_usedConstant = true;
|
||||
|
@ -249,36 +240,21 @@ void TraversalBlock::initializePaths(AqlItemBlock const* items, size_t pos) {
|
|||
"Only id strings or objects with "
|
||||
"_id are allowed");
|
||||
} else {
|
||||
if (planNode->_specializedNeighborsSearch) {
|
||||
// fetch neighbor nodes
|
||||
neighbors(_vertexId);
|
||||
} else {
|
||||
_traverser->setStartVertex(_vertexId);
|
||||
}
|
||||
_traverser->setStartVertex(_vertexId);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AqlValue const& in = items->getValueReference(_pos, _reg);
|
||||
if (in.isObject()) {
|
||||
try {
|
||||
if (planNode->_specializedNeighborsSearch) {
|
||||
// fetch neighbor nodes
|
||||
neighbors(_trx->extractIdString(in.slice()));
|
||||
} else {
|
||||
_traverser->setStartVertex(_trx->extractIdString(in.slice()));
|
||||
}
|
||||
_traverser->setStartVertex(_trx->extractIdString(in.slice()));
|
||||
}
|
||||
catch (...) {
|
||||
// _id or _key not present... ignore this error and fall through
|
||||
}
|
||||
} else if (in.isString()) {
|
||||
_vertexId = in.slice().copyString();
|
||||
if (planNode->_specializedNeighborsSearch) {
|
||||
// fetch neighbor nodes
|
||||
neighbors(_vertexId);
|
||||
} else {
|
||||
_traverser->setStartVertex(_vertexId);
|
||||
}
|
||||
_traverser->setStartVertex(_vertexId);
|
||||
} else {
|
||||
_engine->getQuery()->registerWarning(
|
||||
TRI_ERROR_BAD_PARAMETER, "Invalid input for traversal: Only "
|
||||
|
@ -428,140 +404,3 @@ size_t TraversalBlock::skipSome(size_t atLeast, size_t atMost) {
|
|||
return atMost;
|
||||
DEBUG_END_BLOCK();
|
||||
}
|
||||
|
||||
/// @brief optimized version of neighbors search, must properly implement this
|
||||
void TraversalBlock::neighbors(std::string const& startVertex) {
|
||||
#warning Needs to be rebuild
|
||||
/*
|
||||
std::unordered_set<VPackSlice, arangodb::basics::VelocyPackHelper::VPackStringHash, arangodb::basics::VelocyPackHelper::VPackStringEqual> visited;
|
||||
|
||||
std::vector<VPackSlice> result;
|
||||
result.reserve(1000);
|
||||
|
||||
TransactionBuilderLeaser builder(_trx);
|
||||
builder->add(VPackValue(startVertex));
|
||||
|
||||
std::vector<VPackSlice> startVertices;
|
||||
startVertices.emplace_back(builder->slice());
|
||||
visited.emplace(builder->slice());
|
||||
|
||||
TRI_edge_direction_e direction = TRI_EDGE_ANY;
|
||||
std::string collectionName;
|
||||
traverser::TraverserOptions const* options = _traverser->options();
|
||||
if (options->getCollection(0, collectionName, direction)) {
|
||||
runNeighbors(startVertices, visited, result, direction, 1);
|
||||
}
|
||||
|
||||
TRI_doc_mptr_t mptr;
|
||||
_vertices.clear();
|
||||
_vertices.reserve(result.size());
|
||||
for (auto const& it : result) {
|
||||
VPackValueLength l;
|
||||
char const* p = it.getString(l);
|
||||
StringRef ref(p, l);
|
||||
|
||||
size_t pos = ref.find('/');
|
||||
if (pos == std::string::npos) {
|
||||
// invalid id
|
||||
continue;
|
||||
}
|
||||
|
||||
int res = _trx->documentFastPathLocal(ref.substr(0, pos).toString(), ref.substr(pos + 1).toString(), &mptr);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_vertices.emplace_back(AqlValue(mptr.vpack(), AqlValueFromMasterPointer()));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/// @brief worker for neighbors() function
|
||||
void TraversalBlock::runNeighbors(std::vector<VPackSlice> const& startVertices,
|
||||
std::unordered_set<VPackSlice, arangodb::basics::VelocyPackHelper::VPackStringHash, arangodb::basics::VelocyPackHelper::VPackStringEqual>& visited,
|
||||
std::vector<VPackSlice>& distinct,
|
||||
TRI_edge_direction_e direction,
|
||||
uint64_t depth) {
|
||||
/*
|
||||
std::vector<VPackSlice> nextDepth;
|
||||
bool initialized = false;
|
||||
TraversalNode const* node = static_cast<TraversalNode const*>(getPlanNode());
|
||||
traverser::TraverserOptions const* options = _traverser->options();
|
||||
|
||||
TransactionBuilderLeaser builder(_trx);
|
||||
|
||||
size_t const n = options->collectionCount();
|
||||
std::string collectionName;
|
||||
Transaction::IndexHandle indexHandle;
|
||||
|
||||
std::vector<TRI_doc_mptr_t*> edges;
|
||||
|
||||
for (auto const& startVertex : startVertices) {
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
builder->clear();
|
||||
|
||||
if (!options->getCollectionAndSearchValue(i, startVertex.copyString(), collectionName, indexHandle, *builder.builder())) {
|
||||
TRI_ASSERT(false);
|
||||
}
|
||||
|
||||
std::unique_ptr<OperationCursor> cursor = _trx->indexScan(collectionName,
|
||||
arangodb::Transaction::CursorType::INDEX, indexHandle,
|
||||
builder->slice(), 0, UINT64_MAX, 1000, false);
|
||||
|
||||
if (cursor->failed()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
edges.clear();
|
||||
while (cursor->hasMore()) {
|
||||
cursor->getMoreMptr(edges, 1000);
|
||||
|
||||
for (auto const& it : edges) {
|
||||
VPackSlice edge(it->vpack());
|
||||
VPackSlice v;
|
||||
if (direction == TRI_EDGE_IN) {
|
||||
v = Transaction::extractFromFromDocument(edge);
|
||||
} else {
|
||||
v = Transaction::extractToFromDocument(edge);
|
||||
}
|
||||
|
||||
if (visited.emplace(v).second) {
|
||||
// we have not yet visited this vertex
|
||||
if (depth >= node->minDepth()) {
|
||||
distinct.emplace_back(v);
|
||||
}
|
||||
if (depth < node->maxDepth()) {
|
||||
if (!initialized) {
|
||||
nextDepth.reserve(64);
|
||||
initialized = true;
|
||||
}
|
||||
nextDepth.emplace_back(v);
|
||||
}
|
||||
continue;
|
||||
} else if (direction == TRI_EDGE_ANY) {
|
||||
v = Transaction::extractToFromDocument(edge);
|
||||
if (visited.emplace(v).second) {
|
||||
// we have not yet visited this vertex
|
||||
if (depth >= node->minDepth()) {
|
||||
distinct.emplace_back(v);
|
||||
}
|
||||
if (depth < node->maxDepth()) {
|
||||
if (!initialized) {
|
||||
nextDepth.reserve(64);
|
||||
initialized = true;
|
||||
}
|
||||
nextDepth.emplace_back(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nextDepth.empty()) {
|
||||
runNeighbors(nextDepth, visited, distinct, direction, depth + 1);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -142,16 +142,6 @@ class TraversalBlock : public ExecutionBlock {
|
|||
/// @brief Checks if we output the path
|
||||
bool usesPathOutput() { return _pathVar != nullptr; }
|
||||
|
||||
/// @brief optimized version of neighbors search, must properly implement this
|
||||
void neighbors(std::string const& startVertex);
|
||||
|
||||
/// @brief worker for neighbors() function
|
||||
void runNeighbors(std::vector<VPackSlice> const& startVertices,
|
||||
std::unordered_set<VPackSlice, arangodb::basics::VelocyPackHelper::VPackStringHash, arangodb::basics::VelocyPackHelper::VPackStringEqual>& visited,
|
||||
std::vector<VPackSlice>& distinct,
|
||||
TRI_edge_direction_e direction,
|
||||
uint64_t depth);
|
||||
|
||||
};
|
||||
} // namespace arangodb::aql
|
||||
} // namespace arangodb
|
||||
|
|
|
@ -168,9 +168,6 @@ static bool checkPathVariableAccessFeasible(CalculationNode const* cn,
|
|||
|
||||
for (auto const & node : onePath) {
|
||||
if (node->type == NODE_TYPE_FCALL) {
|
||||
//
|
||||
// we currently don't know how to execute functions in the
|
||||
// traversal (-> TraverserExpression::recursiveCheck
|
||||
return false;
|
||||
}
|
||||
if (node->type == NODE_TYPE_OPERATOR_BINARY_IN ||
|
||||
|
|
|
@ -41,24 +41,33 @@ using namespace arangodb::aql;
|
|||
TraversalNode::EdgeConditionBuilder::EdgeConditionBuilder(
|
||||
TraversalNode const* tn)
|
||||
: _tn(tn), _containsCondition(false) {
|
||||
_modCondition = _tn->_plan->getAst()->createNodeNaryOperator(NODE_TYPE_OPERATOR_NARY_AND);
|
||||
}
|
||||
_modCondition =
|
||||
_tn->_plan->getAst()->createNodeNaryOperator(NODE_TYPE_OPERATOR_NARY_AND);
|
||||
}
|
||||
|
||||
TraversalNode::EdgeConditionBuilder::EdgeConditionBuilder(
|
||||
TraversalNode const* tn, arangodb::basics::Json const& condition)
|
||||
: _tn(tn), _containsCondition(false) {
|
||||
_modCondition = new AstNode(_tn->_plan->getAst(), condition);
|
||||
TRI_ASSERT(_modCondition != nullptr);
|
||||
TRI_ASSERT(_modCondition->type == NODE_TYPE_OPERATOR_NARY_AND);
|
||||
}
|
||||
_modCondition = new AstNode(_tn->_plan->getAst(), condition);
|
||||
TRI_ASSERT(_modCondition != nullptr);
|
||||
TRI_ASSERT(_modCondition->type == NODE_TYPE_OPERATOR_NARY_AND);
|
||||
}
|
||||
|
||||
void TraversalNode::EdgeConditionBuilder::addConditionPart(AstNode const* part) {
|
||||
TraversalNode::EdgeConditionBuilder::EdgeConditionBuilder(
|
||||
TraversalNode const* tn, EdgeConditionBuilder const* other)
|
||||
: _tn(tn),
|
||||
_modCondition(other->_modCondition),
|
||||
_containsCondition(other->_containsCondition) {}
|
||||
|
||||
void TraversalNode::EdgeConditionBuilder::addConditionPart(
|
||||
AstNode const* part) {
|
||||
_modCondition->addMember(part);
|
||||
}
|
||||
|
||||
AstNode* TraversalNode::EdgeConditionBuilder::getOutboundCondition() {
|
||||
if (_containsCondition) {
|
||||
_modCondition->changeMember(_modCondition->numMembers() - 1, _tn->_fromCondition);
|
||||
_modCondition->changeMember(_modCondition->numMembers() - 1,
|
||||
_tn->_fromCondition);
|
||||
} else {
|
||||
for (auto& it : _tn->_globalEdgeConditions) {
|
||||
_modCondition->addMember(it);
|
||||
|
@ -125,7 +134,6 @@ TraversalNode::TraversalNode(ExecutionPlan* plan, size_t id,
|
|||
_inVariable(nullptr),
|
||||
_graphObj(nullptr),
|
||||
_condition(nullptr),
|
||||
_specializedNeighborsSearch(false),
|
||||
_tmpObjVariable(_plan->getAst()->variables()->createTemporaryVariable()),
|
||||
_tmpObjVarNode(_plan->getAst()->createNodeReference(_tmpObjVariable)),
|
||||
_tmpIdNode(_plan->getAst()->createNodeValueString("", 0)),
|
||||
|
@ -318,7 +326,7 @@ TraversalNode::TraversalNode(
|
|||
std::vector<std::unique_ptr<aql::Collection>> const& edgeColls,
|
||||
std::vector<std::unique_ptr<aql::Collection>> const& vertexColls,
|
||||
Variable const* inVariable, std::string const& vertexId,
|
||||
std::vector<TRI_edge_direction_e> directions,
|
||||
std::vector<TRI_edge_direction_e> const& directions,
|
||||
std::unique_ptr<traverser::TraverserOptions>& options)
|
||||
: ExecutionNode(plan, id),
|
||||
_vocbase(vocbase),
|
||||
|
@ -330,7 +338,6 @@ TraversalNode::TraversalNode(
|
|||
_directions(directions),
|
||||
_graphObj(nullptr),
|
||||
_condition(nullptr),
|
||||
_specializedNeighborsSearch(false),
|
||||
_fromCondition(nullptr),
|
||||
_toCondition(nullptr),
|
||||
_optionsBuild(false) {
|
||||
|
@ -361,15 +368,14 @@ TraversalNode::TraversalNode(ExecutionPlan* plan,
|
|||
_inVariable(nullptr),
|
||||
_graphObj(nullptr),
|
||||
_condition(nullptr),
|
||||
_specializedNeighborsSearch(false),
|
||||
_options(std::make_unique<traverser::TraverserOptions>(
|
||||
_plan->getAst()->query()->trx(), base)),
|
||||
_tmpObjVariable(nullptr),
|
||||
_tmpObjVarNode(nullptr),
|
||||
_tmpIdNode(nullptr),
|
||||
_fromCondition(nullptr),
|
||||
_toCondition(nullptr),
|
||||
_optionsBuild(false) {
|
||||
_options = std::make_unique<arangodb::traverser::TraverserOptions>(
|
||||
_plan->getAst()->query()->trx(), base);
|
||||
auto dirList = base.get("directions");
|
||||
TRI_ASSERT(dirList.json() != nullptr);
|
||||
for (size_t i = 0; i < dirList.size(); ++i) {
|
||||
|
@ -569,12 +575,10 @@ TraversalNode::TraversalNode(ExecutionPlan* plan,
|
|||
auto value = Json(TRI_UNKNOWN_MEM_ZONE,
|
||||
static_cast<TRI_json_t const*>(
|
||||
TRI_AtVector(&list->_value._objects, i + 1)));
|
||||
_edgeConditions.emplace(std::make_pair(
|
||||
StringUtils::uint64(key), EdgeConditionBuilder(this, value)));
|
||||
auto ecbuilder = std::make_unique<EdgeConditionBuilder>(this, value);
|
||||
_edgeConditions.emplace(StringUtils::uint64(key), std::move(ecbuilder));
|
||||
}
|
||||
}
|
||||
|
||||
_specializedNeighborsSearch = arangodb::basics::JsonHelper::getBooleanValue(base.json(), "specializedNeighborsSearch", false);
|
||||
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
checkConditionsDefined();
|
||||
|
@ -647,14 +651,6 @@ bool TraversalNode::allDirectionsEqual() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
void TraversalNode::specializeToNeighborsSearch() {
|
||||
TRI_ASSERT(allDirectionsEqual());
|
||||
TRI_ASSERT(!_directions.empty());
|
||||
|
||||
_specializedNeighborsSearch = true;
|
||||
}
|
||||
|
||||
/// @brief toVelocyPack, for TraversalNode
|
||||
void TraversalNode::toVelocyPackHelper(arangodb::velocypack::Builder& nodes,
|
||||
bool verbose) const {
|
||||
ExecutionNode::toVelocyPackHelperGeneric(nodes,
|
||||
|
@ -791,7 +787,7 @@ void TraversalNode::toVelocyPackHelper(arangodb::velocypack::Builder& nodes,
|
|||
nodes.openObject();
|
||||
for (auto const& it : _edgeConditions) {
|
||||
nodes.add(VPackValue(basics::StringUtils::itoa(it.first)));
|
||||
it.second.toVelocyPack(nodes, verbose);
|
||||
it.second->toVelocyPack(nodes, verbose);
|
||||
}
|
||||
nodes.close();
|
||||
}
|
||||
|
@ -840,10 +836,6 @@ ExecutionNode* TraversalNode::clone(ExecutionPlan* plan, bool withDependencies,
|
|||
c->setPathOutput(pathOutVariable);
|
||||
}
|
||||
|
||||
if (_specializedNeighborsSearch) {
|
||||
c->specializeToNeighborsSearch();
|
||||
}
|
||||
|
||||
c->_conditionVariables.reserve(_conditionVariables.size());
|
||||
for (auto const& it: _conditionVariables) {
|
||||
c->_conditionVariables.emplace(it->clone());
|
||||
|
@ -869,7 +861,9 @@ ExecutionNode* TraversalNode::clone(ExecutionPlan* plan, bool withDependencies,
|
|||
_globalVertexConditions.end());
|
||||
|
||||
for (auto const& it : _edgeConditions) {
|
||||
c->_edgeConditions.emplace(it.first, it.second);
|
||||
// Copy the builder
|
||||
auto ecBuilder = std::make_unique<EdgeConditionBuilder>(this, it.second.get());
|
||||
c->_edgeConditions.emplace(it.first, std::move(ecBuilder));
|
||||
}
|
||||
|
||||
for (auto const& it : _vertexConditions) {
|
||||
|
@ -934,7 +928,6 @@ void TraversalNode::prepareOptions() {
|
|||
_options->_tmpVar = _tmpObjVariable;
|
||||
|
||||
size_t numEdgeColls = _edgeColls.size();
|
||||
AstNode* condition = nullptr;
|
||||
bool res = false;
|
||||
EdgeConditionBuilder globalEdgeConditionBuilder(this);
|
||||
Ast* ast = _plan->getAst();
|
||||
|
@ -969,7 +962,7 @@ void TraversalNode::prepareOptions() {
|
|||
_options->_baseLookupInfos.emplace_back(std::move(info));
|
||||
}
|
||||
|
||||
for (std::pair<size_t, EdgeConditionBuilder> it : _edgeConditions) {
|
||||
for (auto& it : _edgeConditions) {
|
||||
auto ins = _options->_depthLookupInfo.emplace(
|
||||
it.first, std::vector<traverser::TraverserOptions::LookupInfo>());
|
||||
// We probably have to adopt minDepth. We cannot fulfill a condition of larger depth anyway
|
||||
|
@ -988,10 +981,10 @@ void TraversalNode::prepareOptions() {
|
|||
traverser::TraverserOptions::LookupInfo info;
|
||||
switch (dir) {
|
||||
case TRI_EDGE_IN:
|
||||
info.indexCondition = builder.getInboundCondition()->clone(ast);
|
||||
info.indexCondition = builder->getInboundCondition()->clone(ast);
|
||||
break;
|
||||
case TRI_EDGE_OUT:
|
||||
info.indexCondition = builder.getOutboundCondition()->clone(ast);
|
||||
info.indexCondition = builder->getOutboundCondition()->clone(ast);
|
||||
break;
|
||||
case TRI_EDGE_ANY:
|
||||
TRI_ASSERT(false);
|
||||
|
@ -1063,11 +1056,11 @@ void TraversalNode::registerCondition(bool isConditionOnEdge,
|
|||
if (isConditionOnEdge) {
|
||||
auto const& it = _edgeConditions.find(conditionLevel);
|
||||
if (it == _edgeConditions.end()) {
|
||||
EdgeConditionBuilder builder(this);
|
||||
builder.addConditionPart(condition);
|
||||
_edgeConditions.emplace(conditionLevel, builder);
|
||||
auto builder = std::make_unique<EdgeConditionBuilder>(this);
|
||||
builder->addConditionPart(condition);
|
||||
_edgeConditions.emplace(conditionLevel, std::move(builder));
|
||||
} else {
|
||||
it->second.addConditionPart(condition);
|
||||
it->second->addConditionPart(condition);
|
||||
}
|
||||
} else {
|
||||
auto const& it = _vertexConditions.find(conditionLevel);
|
||||
|
|
|
@ -50,13 +50,19 @@ class TraversalNode : public ExecutionNode {
|
|||
bool _containsCondition;
|
||||
|
||||
public:
|
||||
EdgeConditionBuilder(TraversalNode const*);
|
||||
explicit EdgeConditionBuilder(TraversalNode const*);
|
||||
|
||||
EdgeConditionBuilder(TraversalNode const*, arangodb::basics::Json const&);
|
||||
EdgeConditionBuilder(TraversalNode const*, arangodb::basics::Json const&);
|
||||
|
||||
~EdgeConditionBuilder() {}
|
||||
EdgeConditionBuilder(TraversalNode const*, EdgeConditionBuilder const*);
|
||||
|
||||
void addConditionPart(AstNode const*);
|
||||
~EdgeConditionBuilder() {}
|
||||
|
||||
EdgeConditionBuilder(EdgeConditionBuilder const&) = delete;
|
||||
|
||||
EdgeConditionBuilder(EdgeConditionBuilder&&) = delete;
|
||||
|
||||
void addConditionPart(AstNode const*);
|
||||
|
||||
AstNode* getOutboundCondition();
|
||||
|
||||
|
@ -87,7 +93,7 @@ class TraversalNode : public ExecutionNode {
|
|||
std::vector<std::unique_ptr<aql::Collection>> const& edgeColls,
|
||||
std::vector<std::unique_ptr<aql::Collection>> const& vertexColls,
|
||||
Variable const* inVariable, std::string const& vertexId,
|
||||
std::vector<TRI_edge_direction_e> directions,
|
||||
std::vector<TRI_edge_direction_e> const& directions,
|
||||
std::unique_ptr<traverser::TraverserOptions>& options);
|
||||
|
||||
public:
|
||||
|
@ -225,8 +231,6 @@ class TraversalNode : public ExecutionNode {
|
|||
|
||||
bool allDirectionsEqual() const;
|
||||
|
||||
void specializeToNeighborsSearch();
|
||||
|
||||
traverser::TraverserOptions* options() const;
|
||||
|
||||
AstNode* getTemporaryRefNode() const;
|
||||
|
@ -303,10 +307,6 @@ class TraversalNode : public ExecutionNode {
|
|||
/// @brief Options for traversals
|
||||
std::unique_ptr<traverser::TraverserOptions> _options;
|
||||
|
||||
/// @brief Defines if you use a specialized neighbors search instead of general purpose
|
||||
/// traversal
|
||||
bool _specializedNeighborsSearch;
|
||||
|
||||
/// @brief Temporary pseudo variable for the currently traversed object.
|
||||
Variable const* _tmpObjVariable;
|
||||
|
||||
|
@ -330,7 +330,7 @@ class TraversalNode : public ExecutionNode {
|
|||
std::vector<AstNode const*> _globalVertexConditions;
|
||||
|
||||
/// @brief List of all depth specific conditions for edges
|
||||
std::unordered_map<size_t, EdgeConditionBuilder> _edgeConditions;
|
||||
std::unordered_map<size_t, std::unique_ptr<EdgeConditionBuilder>> _edgeConditions;
|
||||
|
||||
/// @brief List of all depth specific conditions for vertices
|
||||
std::unordered_map<size_t, AstNode*> _vertexConditions;
|
||||
|
|
|
@ -106,49 +106,6 @@ void ClusterTraverser::fetchVertices() {
|
|||
fetchVerticesFromEngines(_dbname, _engines, _verticesToFetch, _vertices,
|
||||
*(lease.get()));
|
||||
_verticesToFetch.clear();
|
||||
#warning Reimplement this. Fetching Documents Coordinator-Case
|
||||
/*
|
||||
std::vector<TraverserExpression*> expVertices;
|
||||
auto found = _opts.expressions->find(depth);
|
||||
if (found != _opts.expressions->end()) {
|
||||
expVertices = found->second;
|
||||
}
|
||||
|
||||
int res = getFilteredDocumentsOnCoordinator(_dbname, expVertices,
|
||||
verticesToFetch, _vertices);
|
||||
if (res != TRI_ERROR_NO_ERROR &&
|
||||
res != TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
|
||||
// By convention verticesToFetch now contains all _ids of vertices that
|
||||
// could not be found.
|
||||
// Store them as NULL
|
||||
for (auto const& it : verticesToFetch) {
|
||||
VPackBuilder builder;
|
||||
builder.add(VPackValue(VPackValueType::Null));
|
||||
_vertices.emplace(it, builder.steal());
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
bool ClusterTraverser::vertexMatchesCondition(
|
||||
VPackSlice const& v,
|
||||
std::vector<arangodb::traverser::TraverserExpression*> const& exp) {
|
||||
for (auto const& e : exp) {
|
||||
if (!e->isEdgeAccess) {
|
||||
if (v.isNone() || !e->matchesCheck(_trx, v)) {
|
||||
++_filteredPaths;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClusterTraverser::next() {
|
||||
TRI_ASSERT(!_done);
|
||||
return _enumerator->next();
|
||||
}
|
||||
|
||||
aql::AqlValue ClusterTraverser::fetchVertexData(VPackSlice idString) {
|
||||
|
@ -196,15 +153,3 @@ void ClusterTraverser::addEdgeToVelocyPack(arangodb::velocypack::Slice edge,
|
|||
arangodb::velocypack::Builder& result) {
|
||||
result.add(edge);
|
||||
}
|
||||
|
||||
aql::AqlValue ClusterTraverser::lastVertexToAqlValue() {
|
||||
return _enumerator->lastVertexToAqlValue();
|
||||
}
|
||||
|
||||
aql::AqlValue ClusterTraverser::lastEdgeToAqlValue() {
|
||||
return _enumerator->lastEdgeToAqlValue();
|
||||
}
|
||||
|
||||
aql::AqlValue ClusterTraverser::pathToAqlValue(VPackBuilder& builder) {
|
||||
return _enumerator->pathToAqlValue(builder);
|
||||
}
|
||||
|
|
|
@ -64,32 +64,6 @@ class ClusterTraverser final : public Traverser {
|
|||
bool getSingleVertex(arangodb::velocypack::Slice, arangodb::velocypack::Slice,
|
||||
size_t, arangodb::velocypack::Slice&) override;
|
||||
|
||||
bool next() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Builds only the last vertex as AQLValue
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
aql::AqlValue lastVertexToAqlValue() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Builds only the last edge as AQLValue
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
aql::AqlValue lastEdgeToAqlValue() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Builds the complete path as AQLValue
|
||||
/// Has the format:
|
||||
/// {
|
||||
/// vertices: [<vertex-as-velocypack>],
|
||||
/// edges: [<edge-as-velocypack>]
|
||||
/// }
|
||||
/// NOTE: Will clear the given buffer and will leave the path in it.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
aql::AqlValue pathToAqlValue(arangodb::velocypack::Builder&) override;
|
||||
|
||||
protected:
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Function to fetch the real data of a vertex into an AQLValue
|
||||
|
@ -121,9 +95,6 @@ class ClusterTraverser final : public Traverser {
|
|||
|
||||
void fetchVertices();
|
||||
|
||||
bool vertexMatchesCondition(arangodb::velocypack::Slice const&,
|
||||
std::vector<TraverserExpression*> const&);
|
||||
|
||||
std::unordered_map<arangodb::velocypack::Slice, arangodb::velocypack::Slice>
|
||||
_edges;
|
||||
|
||||
|
@ -131,12 +102,8 @@ class ClusterTraverser final : public Traverser {
|
|||
std::shared_ptr<arangodb::velocypack::Buffer<uint8_t>>>
|
||||
_vertices;
|
||||
|
||||
std::stack<std::stack<std::string>> _iteratorCache;
|
||||
|
||||
std::string _dbname;
|
||||
|
||||
arangodb::velocypack::Builder _builder;
|
||||
|
||||
std::unordered_map<ServerID, traverser::TraverserEngineID> const* _engines;
|
||||
|
||||
std::unordered_set<arangodb::velocypack::Slice> _verticesToFetch;
|
||||
|
|
|
@ -183,7 +183,6 @@ void TraverserEngine::getVertexData(VPackSlice vertex, VPackBuilder& builder) {
|
|||
TRI_ASSERT(vertex.isString() || vertex.isArray());
|
||||
builder.openObject();
|
||||
bool found;
|
||||
int res = TRI_ERROR_NO_ERROR;
|
||||
auto workOnOneDocument = [&](VPackSlice v) {
|
||||
found = false;
|
||||
StringRef id(v);
|
||||
|
@ -199,7 +198,7 @@ void TraverserEngine::getVertexData(VPackSlice vertex, VPackBuilder& builder) {
|
|||
}
|
||||
builder.add(v);
|
||||
for (std::string const& shard : shards->second) {
|
||||
res = _trx->documentFastPath(shard, v, builder, false);
|
||||
int res = _trx->documentFastPath(shard, v, builder, false);
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
found = true;
|
||||
// FOUND short circuit.
|
||||
|
@ -233,7 +232,6 @@ void TraverserEngine::getVertexData(VPackSlice vertex, size_t depth,
|
|||
TRI_ASSERT(vertex.isString() || vertex.isArray());
|
||||
size_t read = 0;
|
||||
size_t filtered = 0;
|
||||
int res = TRI_ERROR_NO_ERROR;
|
||||
bool found = false;
|
||||
builder.openObject();
|
||||
builder.add(VPackValue("vertices"));
|
||||
|
@ -251,7 +249,7 @@ void TraverserEngine::getVertexData(VPackSlice vertex, size_t depth,
|
|||
}
|
||||
builder.add(v);
|
||||
for (std::string const& shard : shards->second) {
|
||||
res = _trx->documentFastPath(shard, v, builder, false);
|
||||
int res = _trx->documentFastPath(shard, v, builder, false);
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
read++;
|
||||
found = true;
|
||||
|
|
|
@ -60,6 +60,9 @@ class TraverserEngine {
|
|||
~TraverserEngine();
|
||||
|
||||
public:
|
||||
// The engine is NOT copyable.
|
||||
TraverserEngine(TraverserEngine const&) = delete;
|
||||
|
||||
void getEdges(arangodb::velocypack::Slice, size_t,
|
||||
arangodb::velocypack::Builder&);
|
||||
|
||||
|
|
|
@ -476,7 +476,6 @@ bool Transaction::findIndexHandleForAndNode(
|
|||
Transaction::IndexHandle& usedIndex) const {
|
||||
std::shared_ptr<Index> bestIndex;
|
||||
double bestCost = 0.0;
|
||||
size_t coveredAttributes = 0;
|
||||
|
||||
for (auto const& idx : indexes) {
|
||||
double filterCost = 0.0;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SingleServerTraverser.h"
|
||||
#include "Basics/StringRef.h"
|
||||
#include "Utils/Transaction.h"
|
||||
#include "VocBase/MasterPointer.h"
|
||||
|
||||
|
@ -36,19 +37,16 @@ using namespace arangodb::traverser;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int FetchDocumentById(arangodb::Transaction* trx,
|
||||
std::string const& id,
|
||||
StringRef const& id,
|
||||
TRI_doc_mptr_t* mptr) {
|
||||
size_t pos = id.find('/');
|
||||
if (pos == std::string::npos) {
|
||||
TRI_ASSERT(false);
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
if (id.find('/', pos + 1) != std::string::npos) {
|
||||
TRI_ASSERT(false);
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
int res = trx->documentFastPathLocal(id.substr(0, pos), id.substr(pos + 1), mptr);
|
||||
int res = trx->documentFastPathLocal(id.substr(0, pos).toString(),
|
||||
id.substr(pos + 1).toString(), mptr);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR && res != TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
|
@ -147,8 +145,8 @@ aql::AqlValue SingleServerTraverser::fetchVertexData(VPackSlice id) {
|
|||
|
||||
if (it == _vertices.end()) {
|
||||
TRI_doc_mptr_t mptr;
|
||||
#warning Do we need the copy here?
|
||||
int res = FetchDocumentById(_trx, id.copyString(), &mptr);
|
||||
StringRef ref(id);
|
||||
int res = FetchDocumentById(_trx, ref, &mptr);
|
||||
++_readDocuments;
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return aql::AqlValue(basics::VelocyPackHelper::NullValue());
|
||||
|
@ -173,8 +171,8 @@ void SingleServerTraverser::addVertexToVelocyPack(VPackSlice id,
|
|||
|
||||
if (it == _vertices.end()) {
|
||||
TRI_doc_mptr_t mptr;
|
||||
#warning Do we need the copy here?
|
||||
int res = FetchDocumentById(_trx, id.copyString(), &mptr);
|
||||
StringRef ref(id);
|
||||
int res = FetchDocumentById(_trx, ref, &mptr);
|
||||
++_readDocuments;
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
result.add(basics::VelocyPackHelper::NullValue());
|
||||
|
@ -223,24 +221,3 @@ bool SingleServerTraverser::getSingleVertex(VPackSlice edge, VPackSlice vertex,
|
|||
size_t depth, VPackSlice& result) {
|
||||
return _vertexGetter->getSingleVertex(edge, vertex, depth, result);
|
||||
}
|
||||
|
||||
bool SingleServerTraverser::next() {
|
||||
TRI_ASSERT(!_done);
|
||||
bool res = _enumerator->next();
|
||||
if (!res) {
|
||||
_done = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
aql::AqlValue SingleServerTraverser::lastVertexToAqlValue() {
|
||||
return _enumerator->lastVertexToAqlValue();
|
||||
}
|
||||
|
||||
aql::AqlValue SingleServerTraverser::lastEdgeToAqlValue() {
|
||||
return _enumerator->lastEdgeToAqlValue();
|
||||
}
|
||||
|
||||
aql::AqlValue SingleServerTraverser::pathToAqlValue(VPackBuilder& builder) {
|
||||
return _enumerator->pathToAqlValue(builder);
|
||||
}
|
||||
|
|
|
@ -88,36 +88,6 @@ class SingleServerTraverser final : public Traverser {
|
|||
bool getSingleVertex(arangodb::velocypack::Slice, arangodb::velocypack::Slice,
|
||||
size_t depth, arangodb::velocypack::Slice&) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the next possible path in the graph.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool next() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Builds only the last vertex as AQLValue
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
aql::AqlValue lastVertexToAqlValue() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Builds only the last edge as AQLValue
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
aql::AqlValue lastEdgeToAqlValue() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Builds the complete path as AQLValue
|
||||
/// Has the format:
|
||||
/// {
|
||||
/// vertices: [<vertex-as-velocypack>],
|
||||
/// edges: [<edge-as-velocypack>]
|
||||
/// }
|
||||
/// NOTE: Will clear the given buffer and will leave the path in it.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
aql::AqlValue pathToAqlValue(arangodb::velocypack::Builder&) override;
|
||||
|
||||
protected:
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Function to fetch the real data of a vertex into an AQLValue
|
||||
|
|
|
@ -376,3 +376,24 @@ bool arangodb::traverser::Traverser::vertexMatchesConditions(VPackSlice v, size_
|
|||
return true;
|
||||
}
|
||||
|
||||
bool arangodb::traverser::Traverser::next() {
|
||||
TRI_ASSERT(!_done);
|
||||
bool res = _enumerator->next();
|
||||
if (!res) {
|
||||
_done = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
arangodb::aql::AqlValue arangodb::traverser::Traverser::lastVertexToAqlValue() {
|
||||
return _enumerator->lastVertexToAqlValue();
|
||||
}
|
||||
|
||||
arangodb::aql::AqlValue arangodb::traverser::Traverser::lastEdgeToAqlValue() {
|
||||
return _enumerator->lastEdgeToAqlValue();
|
||||
}
|
||||
|
||||
arangodb::aql::AqlValue arangodb::traverser::Traverser::pathToAqlValue(
|
||||
VPackBuilder& builder) {
|
||||
return _enumerator->pathToAqlValue(builder);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace traverser {
|
|||
|
||||
struct TraverserOptions;
|
||||
|
||||
#warning Deprecated
|
||||
//TODO Deprecated
|
||||
class TraverserExpression {
|
||||
public:
|
||||
bool isEdgeAccess;
|
||||
|
@ -298,11 +298,8 @@ class Traverser {
|
|||
return skipped;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the next possible path in the graph.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual bool next() = 0;
|
||||
bool next();
|
||||
|
||||
/// @brief Function to load the other sides vertex of an edge
|
||||
/// Returns true if the vertex passes filtering conditions
|
||||
|
@ -322,13 +319,13 @@ class Traverser {
|
|||
/// @brief Builds only the last vertex as AQLValue
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual aql::AqlValue lastVertexToAqlValue() = 0;
|
||||
aql::AqlValue lastVertexToAqlValue();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Builds only the last edge as AQLValue
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual aql::AqlValue lastEdgeToAqlValue() = 0;
|
||||
aql::AqlValue lastEdgeToAqlValue();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Builds the complete path as AQLValue
|
||||
|
@ -340,7 +337,7 @@ class Traverser {
|
|||
/// NOTE: Will clear the given buffer and will leave the path in it.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual aql::AqlValue pathToAqlValue(arangodb::velocypack::Builder&) = 0;
|
||||
aql::AqlValue pathToAqlValue(arangodb::velocypack::Builder&);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the number of filtered paths
|
||||
|
|
|
@ -472,7 +472,6 @@ bool arangodb::traverser::TraverserOptions::evaluateEdgeExpression(
|
|||
// The Coordinator never checks conditions. The DBServer is responsible!
|
||||
return true;
|
||||
}
|
||||
bool mustDestroy = false;
|
||||
auto specific = _depthLookupInfo.find(depth);
|
||||
arangodb::aql::Expression* expression = nullptr;
|
||||
|
||||
|
@ -506,17 +505,21 @@ bool arangodb::traverser::TraverserOptions::evaluateEdgeExpression(
|
|||
idNode->stealComputedValue();
|
||||
idNode->setStringValue(vid, vidLength);
|
||||
|
||||
bool mustDestroy = false;
|
||||
aql::AqlValue res = expression->execute(_trx, _ctx, mustDestroy);
|
||||
TRI_ASSERT(res.isBoolean());
|
||||
expression->clearVariable(_tmpVar);
|
||||
return res.toBoolean();
|
||||
bool result = res.toBoolean();
|
||||
if (mustDestroy) {
|
||||
res.destroy();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool arangodb::traverser::TraverserOptions::evaluateVertexExpression(
|
||||
arangodb::velocypack::Slice vertex, size_t depth) const {
|
||||
bool mustDestroy = false;
|
||||
arangodb::aql::Expression* expression = nullptr;
|
||||
|
||||
auto specific = _vertexExpressions.find(depth);
|
||||
|
@ -532,10 +535,15 @@ bool arangodb::traverser::TraverserOptions::evaluateVertexExpression(
|
|||
|
||||
TRI_ASSERT(!expression->isV8());
|
||||
expression->setVariable(_tmpVar, vertex);
|
||||
bool mustDestroy = false;
|
||||
aql::AqlValue res = expression->execute(_trx, _ctx, mustDestroy);
|
||||
TRI_ASSERT(res.isBoolean());
|
||||
bool result = res.toBoolean();
|
||||
expression->clearVariable(_tmpVar);
|
||||
return res.toBoolean();
|
||||
if (mustDestroy) {
|
||||
res.destroy();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
arangodb::traverser::EdgeCursor*
|
||||
|
|
|
@ -115,6 +115,7 @@ struct TraverserOptions {
|
|||
_baseVertexExpression(nullptr),
|
||||
_tmpVar(nullptr),
|
||||
_ctx(new aql::FixedVarExpressionContext()),
|
||||
_traverser(nullptr),
|
||||
minDepth(1),
|
||||
maxDepth(1),
|
||||
useBreadthFirst(false),
|
||||
|
|
Loading…
Reference in New Issue