mirror of https://gitee.com/bigwinds/arangodb
Intermediate State: Moved Traversals to use Slices above Strings to compare. Also Preperation to use different indexes. This state compiles but is not functional.
This commit is contained in:
parent
5b1e1b7496
commit
aa1dc2a083
|
@ -632,6 +632,7 @@ void TraversalNode::fillTraversalOptions(
|
||||||
EdgeConditionBuilder globalEdgeConditionBuilder(this);
|
EdgeConditionBuilder globalEdgeConditionBuilder(this);
|
||||||
|
|
||||||
opts._baseIndexHandles.reserve(numEdgeColls);
|
opts._baseIndexHandles.reserve(numEdgeColls);
|
||||||
|
opts._baseConditions.reserve(numEdgeColls);
|
||||||
// Compute Edge Indexes. First default indexes:
|
// Compute Edge Indexes. First default indexes:
|
||||||
for (size_t i = 0; i < numEdgeColls; ++i) {
|
for (size_t i = 0; i < numEdgeColls; ++i) {
|
||||||
auto dir = _directions[i];
|
auto dir = _directions[i];
|
||||||
|
@ -649,6 +650,7 @@ void TraversalNode::fillTraversalOptions(
|
||||||
opts._baseIndexHandles);
|
opts._baseIndexHandles);
|
||||||
TRI_ASSERT(res); // Right now we have an enforced edge index which wil
|
TRI_ASSERT(res); // Right now we have an enforced edge index which wil
|
||||||
// always fit.
|
// always fit.
|
||||||
|
opts._baseConditions.emplace_back(condition->clone(_ast));
|
||||||
condition = globalEdgeConditionBuilder.getOutboundCondition();
|
condition = globalEdgeConditionBuilder.getOutboundCondition();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -657,15 +659,19 @@ void TraversalNode::fillTraversalOptions(
|
||||||
_edgeColls[i], condition, _tmpObjVariable, &sort, 1000,
|
_edgeColls[i], condition, _tmpObjVariable, &sort, 1000,
|
||||||
opts._baseIndexHandles);
|
opts._baseIndexHandles);
|
||||||
TRI_ASSERT(res); // We have an enforced edge index which wil always fit.
|
TRI_ASSERT(res); // We have an enforced edge index which wil always fit.
|
||||||
|
opts._baseConditions.emplace_back(condition->clone(_ast));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::pair<size_t, EdgeConditionBuilder> it : _edgeConditions) {
|
for (std::pair<size_t, EdgeConditionBuilder> it : _edgeConditions) {
|
||||||
auto ins = opts._depthIndexHandles.emplace(
|
auto ins = opts._depthIndexHandles.emplace(
|
||||||
it.first, std::vector<Transaction::IndexHandle>());
|
it.first, std::make_pair(std::vector<Transaction::IndexHandle>(),
|
||||||
|
std::vector<AstNode const*>()));
|
||||||
TRI_ASSERT(ins.second);
|
TRI_ASSERT(ins.second);
|
||||||
|
|
||||||
auto& idxList = ins.first->second;
|
auto& idxList = ins.first->second.first;
|
||||||
|
auto& condList = ins.first->second.second;
|
||||||
idxList.reserve(numEdgeColls);
|
idxList.reserve(numEdgeColls);
|
||||||
|
condList.reserve(numEdgeColls);
|
||||||
// Compute Edge Indexes. First default indexes:
|
// Compute Edge Indexes. First default indexes:
|
||||||
for (size_t i = 0; i < numEdgeColls; ++i) {
|
for (size_t i = 0; i < numEdgeColls; ++i) {
|
||||||
auto dir = _directions[i];
|
auto dir = _directions[i];
|
||||||
|
@ -682,6 +688,7 @@ void TraversalNode::fillTraversalOptions(
|
||||||
_edgeColls[i], condition, _tmpObjVariable, &sort, 1000, idxList);
|
_edgeColls[i], condition, _tmpObjVariable, &sort, 1000, idxList);
|
||||||
TRI_ASSERT(res); // Right now we have an enforced edge index which wil
|
TRI_ASSERT(res); // Right now we have an enforced edge index which wil
|
||||||
// always fit.
|
// always fit.
|
||||||
|
condList.emplace_back(condition);
|
||||||
condition = it.second.getOutboundCondition();
|
condition = it.second.getOutboundCondition();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -689,32 +696,10 @@ void TraversalNode::fillTraversalOptions(
|
||||||
res = trx->getBestIndexHandleForFilterCondition(
|
res = trx->getBestIndexHandleForFilterCondition(
|
||||||
_edgeColls[i], condition, _tmpObjVariable, &sort, 1000, idxList);
|
_edgeColls[i], condition, _tmpObjVariable, &sort, 1000, idxList);
|
||||||
TRI_ASSERT(res); // We have an enforced edge index which wil always fit.
|
TRI_ASSERT(res); // We have an enforced edge index which wil always fit.
|
||||||
|
condList.emplace_back(condition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VPackBuilder ulf;
|
|
||||||
ulf.openObject();
|
|
||||||
ulf.add(VPackValue("base"));
|
|
||||||
ulf.openArray();
|
|
||||||
for (auto const& idx : opts._baseIndexHandles) {
|
|
||||||
ulf.openObject();
|
|
||||||
idx.toVelocyPack(ulf, false);
|
|
||||||
ulf.close();
|
|
||||||
}
|
|
||||||
ulf.close();
|
|
||||||
for (auto const& it : opts._depthIndexHandles) {
|
|
||||||
ulf.add(VPackValue(std::to_string(it.first)));
|
|
||||||
ulf.openArray();
|
|
||||||
for (auto const& idx : it.second) {
|
|
||||||
ulf.openObject();
|
|
||||||
idx.toVelocyPack(ulf, false);
|
|
||||||
ulf.close();
|
|
||||||
}
|
|
||||||
ulf.close();
|
|
||||||
}
|
|
||||||
ulf.close();
|
|
||||||
LOG(ERR) << ulf.toJson();
|
|
||||||
|
|
||||||
opts.useBreadthFirst = _options.useBreadthFirst;
|
opts.useBreadthFirst = _options.useBreadthFirst;
|
||||||
opts.uniqueVertices = _options.uniqueVertices;
|
opts.uniqueVertices = _options.uniqueVertices;
|
||||||
opts.uniqueEdges = _options.uniqueEdges;
|
opts.uniqueEdges = _options.uniqueEdges;
|
||||||
|
|
|
@ -32,68 +32,103 @@ using namespace arangodb;
|
||||||
|
|
||||||
using ClusterTraverser = arangodb::traverser::ClusterTraverser;
|
using ClusterTraverser = arangodb::traverser::ClusterTraverser;
|
||||||
|
|
||||||
bool ClusterTraverser::VertexGetter::getVertex(std::string const& edgeId,
|
bool ClusterTraverser::VertexGetter::getVertex(
|
||||||
std::string const& vertexId,
|
VPackSlice edge, std::vector<VPackSlice>& result) {
|
||||||
size_t depth,
|
VPackSlice cmp = result.back();
|
||||||
std::string& result) {
|
VPackSlice from = edge.get(StaticStrings::FromString);
|
||||||
|
|
||||||
auto it = _traverser->_edges.find(edgeId);
|
|
||||||
if (it != _traverser->_edges.end()) {
|
|
||||||
VPackSlice slice(it->second->data());
|
|
||||||
std::string from = slice.get(StaticStrings::FromString).copyString();
|
|
||||||
if (from != vertexId) {
|
|
||||||
result = std::move(from);
|
|
||||||
} else {
|
|
||||||
std::string to = slice.get(StaticStrings::ToString).copyString();
|
|
||||||
result = std::move(to);
|
|
||||||
}
|
|
||||||
#warning Here we have to execute VertexFilter
|
#warning Here we have to execute VertexFilter
|
||||||
/// If the vertex is not cached in _traverser->_vertices => incr. _filteredPath return false;
|
/// If the vertex is not cached in _traverser->_vertices => incr. _filteredPath return false;
|
||||||
/// Else check condition if ok => return true, else return false.
|
/// Else check condition if ok => return true, else return false.
|
||||||
/// When returning false set result = ""
|
/// When returning false set result = ""
|
||||||
|
if (arangodb::basics::VelocyPackHelper::compare(cmp, from, false) != 0) {
|
||||||
|
result.emplace_back(from);
|
||||||
|
} else {
|
||||||
|
result.emplace_back(edge.get(StaticStrings::ToString));
|
||||||
}
|
}
|
||||||
// This should never be reached
|
return true;
|
||||||
result = "";
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClusterTraverser::VertexGetter::getSingleVertex(VPackSlice edge,
|
||||||
|
VPackSlice cmp,
|
||||||
|
size_t depth,
|
||||||
|
VPackSlice& result) {
|
||||||
|
VPackSlice from = edge.get(StaticStrings::FromString);
|
||||||
|
#warning Here we have to execute VertexFilter
|
||||||
|
/// If the vertex is not cached in _traverser->_vertices => incr. _filteredPath return false;
|
||||||
|
/// Else check condition if ok => return true, else return false.
|
||||||
|
/// When returning false set result = ""
|
||||||
|
if (arangodb::basics::VelocyPackHelper::compare(cmp, from, false) != 0) {
|
||||||
|
result = from;
|
||||||
|
} else {
|
||||||
|
result = edge.get(StaticStrings::ToString);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ClusterTraverser::VertexGetter::reset() {
|
void ClusterTraverser::VertexGetter::reset() {
|
||||||
// Nothing to do here. Subclass has to clear list of already returned vertices.
|
// Nothing to do here. Subclass has to clear list of already returned vertices.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClusterTraverser::UniqueVertexGetter::getVertex(
|
bool ClusterTraverser::UniqueVertexGetter::getVertex(
|
||||||
std::string const& edgeId, std::string const& vertexId, size_t depth,
|
VPackSlice edge, std::vector<VPackSlice>& result) {
|
||||||
std::string& result) {
|
VPackSlice toAdd = edge.get(StaticStrings::FromString);
|
||||||
|
VPackSlice cmp = result.back();
|
||||||
auto it = _traverser->_edges.find(edgeId);
|
|
||||||
if (it != _traverser->_edges.end()) {
|
|
||||||
VPackSlice slice(it->second->data());
|
|
||||||
std::string from = slice.get(StaticStrings::FromString).copyString();
|
|
||||||
if (from != vertexId) {
|
|
||||||
result = std::move(from);
|
|
||||||
} else {
|
|
||||||
std::string to = slice.get(StaticStrings::ToString).copyString();
|
|
||||||
result = std::move(to);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_returnedVertices.find(result) != _returnedVertices.end()) {
|
|
||||||
// This vertex is not unique.
|
|
||||||
++_traverser->_filteredPaths;
|
|
||||||
result = "";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (arangodb::basics::VelocyPackHelper::compare(toAdd, cmp, false) == 0) {
|
||||||
|
toAdd = edge.get(StaticStrings::ToString);
|
||||||
|
}
|
||||||
|
|
||||||
#warning Here we have to execute VertexFilter
|
#warning Here we have to execute VertexFilter
|
||||||
/// If the vertex is not cached in _traverser->_vertices => incr. _filteredPath return false;
|
/// If the vertex is not cached in _traverser->_vertices => incr. _filteredPath return false;
|
||||||
/// Else check condition if ok => return true, else return false.
|
/// Else check condition if ok => return true, else return false.
|
||||||
/// When returning false set result = ""
|
/// When returning false set result = ""
|
||||||
/// When returning true: _returnedVertices.emplace(result)
|
/// When returning true: _returnedVertices.emplace(result)
|
||||||
|
|
||||||
|
if (_returnedVertices.find(toAdd) != _returnedVertices.end()) {
|
||||||
|
// This vertex is not unique.
|
||||||
|
++_traverser->_filteredPaths;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
_returnedVertices.emplace(toAdd);
|
||||||
|
result.emplace_back(toAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should never be reached
|
// This should never be reached
|
||||||
result = "";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClusterTraverser::UniqueVertexGetter::getSingleVertex(
|
||||||
|
VPackSlice edge, VPackSlice cmp, size_t depth, VPackSlice& result) {
|
||||||
|
|
||||||
|
result = edge.get(StaticStrings::FromString);
|
||||||
|
|
||||||
|
if (arangodb::basics::VelocyPackHelper::compare(result, cmp, false) == 0) {
|
||||||
|
result = edge.get(StaticStrings::ToString);
|
||||||
|
}
|
||||||
|
|
||||||
|
#warning Here we have to execute VertexFilter
|
||||||
|
/// If the vertex is not cached in _traverser->_vertices => incr. _filteredPath return false;
|
||||||
|
/// Else check condition if ok => return true, else return false.
|
||||||
|
/// When returning false set result = ""
|
||||||
|
/// When returning true: _returnedVertices.emplace(result)
|
||||||
|
|
||||||
|
if (_returnedVertices.find(result) != _returnedVertices.end()) {
|
||||||
|
// This vertex is not unique.
|
||||||
|
++_traverser->_filteredPaths;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
_returnedVertices.emplace(result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should never be reached
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ClusterTraverser::UniqueVertexGetter::reset() {
|
void ClusterTraverser::UniqueVertexGetter::reset() {
|
||||||
_returnedVertices.clear();
|
_returnedVertices.clear();
|
||||||
}
|
}
|
||||||
|
@ -228,7 +263,7 @@ void ClusterTraverser::ClusterEdgeGetter::getEdge(
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterTraverser::ClusterEdgeGetter::getAllEdges(
|
void ClusterTraverser::ClusterEdgeGetter::getAllEdges(
|
||||||
std::string const& startVertex, std::unordered_set<std::string>& result,
|
VPackSlice startVertex, std::unordered_set<VPackSlice>& result,
|
||||||
size_t depth) {
|
size_t depth) {
|
||||||
std::string collName;
|
std::string collName;
|
||||||
TRI_edge_direction_e dir;
|
TRI_edge_direction_e dir;
|
||||||
|
@ -300,16 +335,14 @@ void ClusterTraverser::ClusterEdgeGetter::getAllEdges(
|
||||||
|
|
||||||
void ClusterTraverser::setStartVertex(std::string const& id) {
|
void ClusterTraverser::setStartVertex(std::string const& id) {
|
||||||
_vertexGetter->reset();
|
_vertexGetter->reset();
|
||||||
if (_opts.useBreadthFirst) {
|
|
||||||
_enumerator.reset(
|
|
||||||
new arangodb::traverser::BreadthFirstEnumerator(this, id, &_opts));
|
|
||||||
_vertexGetter->setStartVertex(id);
|
|
||||||
} else {
|
|
||||||
_enumerator.reset(
|
|
||||||
new arangodb::traverser::DepthFirstEnumerator(this, id, &_opts));
|
|
||||||
}
|
|
||||||
_done = false;
|
_done = false;
|
||||||
auto it = _vertices.find(id);
|
#warning Arraaghghh Who is responsible for the Builder and Slice?
|
||||||
|
|
||||||
|
VPackBuilder tmp;
|
||||||
|
tmp.add(VPackValue(id));
|
||||||
|
VPackSlice idSlice = tmp.slice();
|
||||||
|
|
||||||
|
auto it = _vertices.find(idSlice);
|
||||||
if (it == _vertices.end()) {
|
if (it == _vertices.end()) {
|
||||||
size_t firstSlash = id.find("/");
|
size_t firstSlash = id.find("/");
|
||||||
if (firstSlash == std::string::npos ||
|
if (firstSlash == std::string::npos ||
|
||||||
|
@ -322,7 +355,7 @@ void ClusterTraverser::setStartVertex(std::string const& id) {
|
||||||
std::unordered_set<std::string> vertexToFetch;
|
std::unordered_set<std::string> vertexToFetch;
|
||||||
vertexToFetch.emplace(id);
|
vertexToFetch.emplace(id);
|
||||||
fetchVertices(vertexToFetch, 0); // this inserts the vertex
|
fetchVertices(vertexToFetch, 0); // this inserts the vertex
|
||||||
it = _vertices.find(id);
|
it = _vertices.find(idSlice);
|
||||||
if (it == _vertices.end()) {
|
if (it == _vertices.end()) {
|
||||||
// We can stop here. The start vertex does not match condition.
|
// We can stop here. The start vertex does not match condition.
|
||||||
++_filteredPaths;
|
++_filteredPaths;
|
||||||
|
@ -334,6 +367,16 @@ void ClusterTraverser::setStartVertex(std::string const& id) {
|
||||||
if (_opts.evaluateVertexExpression(VPackSlice(it->second->data()), 0)) {
|
if (_opts.evaluateVertexExpression(VPackSlice(it->second->data()), 0)) {
|
||||||
// We can stop here. The start vertex does not match condition
|
// We can stop here. The start vertex does not match condition
|
||||||
_done = true;
|
_done = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VPackSlice startId(it->second->data());
|
||||||
|
if (_opts.useBreadthFirst) {
|
||||||
|
_enumerator.reset(
|
||||||
|
new arangodb::traverser::BreadthFirstEnumerator(this, startId, &_opts));
|
||||||
|
_vertexGetter->setStartVertex(startId);
|
||||||
|
} else {
|
||||||
|
_enumerator.reset(
|
||||||
|
new arangodb::traverser::DepthFirstEnumerator(this, startId, &_opts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,17 +387,22 @@ void ClusterTraverser::getEdge(std::string const& startVertex,
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterTraverser::getAllEdges(
|
void ClusterTraverser::getAllEdges(
|
||||||
std::string const& startVertex, std::unordered_set<std::string>& result,
|
VPackSlice startVertex, std::unordered_set<VPackSlice>& result,
|
||||||
size_t depth) {
|
size_t depth) {
|
||||||
return _edgeGetter->getAllEdges(startVertex, result, depth);
|
return _edgeGetter->getAllEdges(startVertex, result, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClusterTraverser::getVertex(std::string const& edgeId,
|
bool ClusterTraverser::getVertex(VPackSlice edge,
|
||||||
std::string const& vertexId, size_t depth,
|
std::vector<VPackSlice>& result) {
|
||||||
std::string& result) {
|
return _vertexGetter->getVertex(edge, result);
|
||||||
return _vertexGetter->getVertex(edgeId, vertexId, depth, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClusterTraverser::getSingleVertex(VPackSlice edge, VPackSlice comp,
|
||||||
|
size_t depth, VPackSlice& result) {
|
||||||
|
return _vertexGetter->getSingleVertex(edge, comp, depth, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ClusterTraverser::fetchVertices(std::unordered_set<std::string>& verticesToFetch, size_t depth) {
|
void ClusterTraverser::fetchVertices(std::unordered_set<std::string>& verticesToFetch, size_t depth) {
|
||||||
_readDocuments += verticesToFetch.size();
|
_readDocuments += verticesToFetch.size();
|
||||||
|
|
||||||
|
@ -400,11 +448,6 @@ bool ClusterTraverser::vertexMatchesCondition(
|
||||||
|
|
||||||
bool ClusterTraverser::next() {
|
bool ClusterTraverser::next() {
|
||||||
TRI_ASSERT(!_done);
|
TRI_ASSERT(!_done);
|
||||||
if (_pruneNext) {
|
|
||||||
_pruneNext = false;
|
|
||||||
_enumerator->prune();
|
|
||||||
}
|
|
||||||
TRI_ASSERT(!_pruneNext);
|
|
||||||
return _enumerator->next();
|
return _enumerator->next();
|
||||||
/*
|
/*
|
||||||
if (_opts.useBreadthFirst &&
|
if (_opts.useBreadthFirst &&
|
||||||
|
@ -430,26 +473,25 @@ bool ClusterTraverser::next() {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
aql::AqlValue ClusterTraverser::fetchVertexData(std::string const& id) {
|
aql::AqlValue ClusterTraverser::fetchVertexData(VPackSlice idString) {
|
||||||
auto cached = _vertices.find(id);
|
TRI_ASSERT(idString.isString());
|
||||||
|
auto cached = _vertices.find(idString);
|
||||||
// All vertices are cached!!
|
// All vertices are cached!!
|
||||||
TRI_ASSERT(cached != _vertices.end());
|
TRI_ASSERT(cached != _vertices.end());
|
||||||
return aql::AqlValue((*cached).second->data());
|
return aql::AqlValue((*cached).second->data());
|
||||||
}
|
}
|
||||||
|
|
||||||
aql::AqlValue ClusterTraverser::fetchEdgeData(std::string const& id) {
|
aql::AqlValue ClusterTraverser::fetchEdgeData(VPackSlice edge) {
|
||||||
auto cached = _edges.find(id);
|
return aql::AqlValue(edge);
|
||||||
// All edges are cached!!
|
|
||||||
TRI_ASSERT(cached != _edges.end());
|
|
||||||
return aql::AqlValue((*cached).second->data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Function to add the real data of a vertex into a velocypack builder
|
/// @brief Function to add the real data of a vertex into a velocypack builder
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ClusterTraverser::addVertexToVelocyPack(std::string const& id,
|
void ClusterTraverser::addVertexToVelocyPack(VPackSlice id,
|
||||||
arangodb::velocypack::Builder& result) {
|
VPackBuilder& result) {
|
||||||
|
TRI_ASSERT(id.isString());
|
||||||
auto cached = _vertices.find(id);
|
auto cached = _vertices.find(id);
|
||||||
// All vertices are cached!!
|
// All vertices are cached!!
|
||||||
TRI_ASSERT(cached != _vertices.end());
|
TRI_ASSERT(cached != _vertices.end());
|
||||||
|
@ -460,12 +502,9 @@ void ClusterTraverser::addVertexToVelocyPack(std::string const& id,
|
||||||
/// @brief Function to add the real data of an edge into a velocypack builder
|
/// @brief Function to add the real data of an edge into a velocypack builder
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ClusterTraverser::addEdgeToVelocyPack(std::string const& id,
|
void ClusterTraverser::addEdgeToVelocyPack(arangodb::velocypack::Slice edge,
|
||||||
arangodb::velocypack::Builder& result) {
|
arangodb::velocypack::Builder& result) {
|
||||||
auto cached = _edges.find(id);
|
result.add(edge);
|
||||||
// All edges are cached!!
|
|
||||||
TRI_ASSERT(cached != _edges.end());
|
|
||||||
result.add(VPackSlice((*cached).second->data()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aql::AqlValue ClusterTraverser::lastVertexToAqlValue() {
|
aql::AqlValue ClusterTraverser::lastVertexToAqlValue() {
|
||||||
|
|
|
@ -56,7 +56,7 @@ class ClusterTraverser final : public Traverser {
|
||||||
~ClusterTraverser() {
|
~ClusterTraverser() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStartVertex(std::string const&) override;
|
void setStartVertex(std::string const& id) override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Function to load edges for a node
|
/// @brief Function to load edges for a node
|
||||||
|
@ -69,16 +69,22 @@ class ClusterTraverser final : public Traverser {
|
||||||
/// @brief Function to load all edges for a list of nodes
|
/// @brief Function to load all edges for a list of nodes
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void getAllEdges(std::string const&, std::unordered_set<std::string>&,
|
void getAllEdges(arangodb::velocypack::Slice,
|
||||||
|
std::unordered_set<arangodb::velocypack::Slice>&,
|
||||||
size_t) override;
|
size_t) override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief Function to load the other sides vertex of an edge
|
/// @brief Function to load the other sides vertex of an edge
|
||||||
/// Returns true if the vertex passes filtering conditions
|
/// Returns true if the vertex passes filtering conditions
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
/// Also apppends the _id value of the vertex in the given vector
|
||||||
|
|
||||||
bool getVertex(std::string const&, std::string const&, size_t,
|
bool getVertex(arangodb::velocypack::Slice,
|
||||||
std::string&) override;
|
std::vector<arangodb::velocypack::Slice>&) override;
|
||||||
|
|
||||||
|
/// @brief Function to load the other sides vertex of an edge
|
||||||
|
/// Returns true if the vertex passes filtering conditions
|
||||||
|
|
||||||
|
bool getSingleVertex(arangodb::velocypack::Slice, arangodb::velocypack::Slice,
|
||||||
|
size_t, arangodb::velocypack::Slice&) override;
|
||||||
|
|
||||||
bool next() override;
|
bool next() override;
|
||||||
|
|
||||||
|
@ -111,26 +117,26 @@ class ClusterTraverser final : public Traverser {
|
||||||
/// @brief Function to fetch the real data of a vertex into an AQLValue
|
/// @brief Function to fetch the real data of a vertex into an AQLValue
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
aql::AqlValue fetchVertexData(std::string const&) override;
|
aql::AqlValue fetchVertexData(arangodb::velocypack::Slice) override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Function to fetch the real data of an edge into an AQLValue
|
/// @brief Function to fetch the real data of an edge into an AQLValue
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
aql::AqlValue fetchEdgeData(std::string const&) override;
|
aql::AqlValue fetchEdgeData(arangodb::velocypack::Slice) override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Function to add the real data of a vertex into a velocypack builder
|
/// @brief Function to add the real data of a vertex into a velocypack builder
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void addVertexToVelocyPack(std::string const&,
|
void addVertexToVelocyPack(arangodb::velocypack::Slice,
|
||||||
arangodb::velocypack::Builder&) override;
|
arangodb::velocypack::Builder&) override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Function to add the real data of an edge into a velocypack builder
|
/// @brief Function to add the real data of an edge into a velocypack builder
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void addEdgeToVelocyPack(std::string const&,
|
void addEdgeToVelocyPack(arangodb::velocypack::Slice,
|
||||||
arangodb::velocypack::Builder&) override;
|
arangodb::velocypack::Builder&) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -147,11 +153,15 @@ class ClusterTraverser final : public Traverser {
|
||||||
|
|
||||||
virtual ~VertexGetter() = default;
|
virtual ~VertexGetter() = default;
|
||||||
|
|
||||||
virtual bool getVertex(std::string const&, std::string const&, size_t,
|
virtual bool getVertex(arangodb::velocypack::Slice,
|
||||||
std::string&);
|
std::vector<arangodb::velocypack::Slice>&);
|
||||||
|
|
||||||
|
virtual bool getSingleVertex(arangodb::velocypack::Slice,
|
||||||
|
arangodb::velocypack::Slice, size_t,
|
||||||
|
arangodb::velocypack::Slice&);
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
||||||
virtual void setStartVertex(std::string const&) {}
|
virtual void setStartVertex(arangodb::velocypack::Slice) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ClusterTraverser* _traverser;
|
ClusterTraverser* _traverser;
|
||||||
|
@ -164,17 +174,21 @@ class ClusterTraverser final : public Traverser {
|
||||||
|
|
||||||
~UniqueVertexGetter() = default;
|
~UniqueVertexGetter() = default;
|
||||||
|
|
||||||
bool getVertex(std::string const&, std::string const&, size_t,
|
bool getVertex(arangodb::velocypack::Slice,
|
||||||
std::string&) override;
|
std::vector<arangodb::velocypack::Slice>&) override;
|
||||||
|
|
||||||
|
bool getSingleVertex(arangodb::velocypack::Slice,
|
||||||
|
arangodb::velocypack::Slice, size_t,
|
||||||
|
arangodb::velocypack::Slice&) override;
|
||||||
|
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
void setStartVertex(std::string const& id) override {
|
void setStartVertex(arangodb::velocypack::Slice id) override {
|
||||||
_returnedVertices.emplace(id);
|
_returnedVertices.emplace(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_set<std::string> _returnedVertices;
|
std::unordered_set<arangodb::velocypack::Slice> _returnedVertices;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClusterEdgeGetter {
|
class ClusterEdgeGetter {
|
||||||
|
@ -185,7 +199,9 @@ class ClusterTraverser final : public Traverser {
|
||||||
void getEdge(std::string const&, std::vector<std::string>&, size_t*&,
|
void getEdge(std::string const&, std::vector<std::string>&, size_t*&,
|
||||||
size_t&);
|
size_t&);
|
||||||
|
|
||||||
void getAllEdges(std::string const&, std::unordered_set<std::string>&, size_t depth);
|
void getAllEdges(arangodb::velocypack::Slice,
|
||||||
|
std::unordered_set<arangodb::velocypack::Slice>&,
|
||||||
|
size_t depth);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClusterTraverser* _traverser;
|
ClusterTraverser* _traverser;
|
||||||
|
@ -197,7 +213,7 @@ class ClusterTraverser final : public Traverser {
|
||||||
std::shared_ptr<arangodb::velocypack::Buffer<uint8_t>>>
|
std::shared_ptr<arangodb::velocypack::Buffer<uint8_t>>>
|
||||||
_edges;
|
_edges;
|
||||||
|
|
||||||
std::unordered_map<std::string,
|
std::unordered_map<arangodb::velocypack::Slice,
|
||||||
std::shared_ptr<arangodb::velocypack::Buffer<uint8_t>>>
|
std::shared_ptr<arangodb::velocypack::Buffer<uint8_t>>>
|
||||||
_vertices;
|
_vertices;
|
||||||
|
|
||||||
|
|
|
@ -32,78 +32,53 @@ using TraverserOptions = arangodb::traverser::TraverserOptions;
|
||||||
bool DepthFirstEnumerator::next() {
|
bool DepthFirstEnumerator::next() {
|
||||||
if (_isFirst) {
|
if (_isFirst) {
|
||||||
_isFirst = false;
|
_isFirst = false;
|
||||||
|
// Initialze the first cursor
|
||||||
|
_opts->nextCursor(_enumeratedPath.vertices.back(), 0);
|
||||||
if (_opts->minDepth == 0) {
|
if (_opts->minDepth == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_enumeratedPath.edges.size() == _opts->maxDepth) {
|
if (_enumeratedPath.vertices.empty()) {
|
||||||
// we have reached the maximal search depth.
|
// We are done;
|
||||||
// We can prune this path and go to the next.
|
return false;
|
||||||
prune();
|
}
|
||||||
|
if (_enumeratedPath.edges.size() < _opts->maxDepth) {
|
||||||
|
// We are not done with this path, so
|
||||||
|
// we reserve the cursor for next depth
|
||||||
|
auto cursor = _opts->nextCursor(_enumeratedPath.vertices.back(),
|
||||||
|
_enumeratedPath.vertices.size());
|
||||||
|
if (cursor != nullptr) {
|
||||||
|
_edgeCursors.emplace(cursor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This path is at the end. cut the last step
|
||||||
|
_enumeratedPath.vertices.pop_back();
|
||||||
|
_enumeratedPath.edges.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid tail recursion. May crash on high search depth
|
while (!_edgeCursors.empty()) {
|
||||||
while (true) {
|
auto cursor = _edgeCursors.top();
|
||||||
if (_lastEdges.empty()) {
|
if (cursor->next(_enumeratedPath.edges)) {
|
||||||
_enumeratedPath.edges.clear();
|
#warning not yet finished
|
||||||
_enumeratedPath.vertices.clear();
|
// TODO UNIQUE_PATH
|
||||||
return false;
|
// We have to check if edge and vertex is valid
|
||||||
}
|
if (_traverser->getVertex(_enumeratedPath.edges.back(),
|
||||||
_traverser->getEdge(_enumeratedPath.vertices.back(), _enumeratedPath.edges,
|
_enumeratedPath.vertices)) {
|
||||||
_lastEdges.top(), _lastEdgesIdx.top());
|
// case both are valid.
|
||||||
if (_lastEdges.top() != nullptr) {
|
// TODO UNIQUE_PATH
|
||||||
// Could continue the path in the next depth.
|
|
||||||
_lastEdges.push(nullptr);
|
|
||||||
_lastEdgesIdx.push(0);
|
|
||||||
std::string v;
|
|
||||||
bool isValid = _traverser->getVertex(_enumeratedPath.edges.back(),
|
|
||||||
_enumeratedPath.vertices.back(),
|
|
||||||
_enumeratedPath.vertices.size(), v);
|
|
||||||
_enumeratedPath.vertices.push_back(v);
|
|
||||||
TRI_ASSERT(_enumeratedPath.vertices.size() ==
|
|
||||||
_enumeratedPath.edges.size() + 1);
|
|
||||||
if (isValid) {
|
|
||||||
if (_enumeratedPath.edges.size() < _opts->minDepth) {
|
|
||||||
// The path is ok as a prefix. But to short to be returned.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_opts->uniqueVertices == TraverserOptions::UniquenessLevel::PATH) {
|
|
||||||
// it is sufficient to check if any of the vertices on the path is equal to the end.
|
|
||||||
// Then we prune and any intermediate equality cannot happen.
|
|
||||||
auto& last = _enumeratedPath.vertices.back();
|
|
||||||
auto found = std::find(_enumeratedPath.vertices.begin(), _enumeratedPath.vertices.end(), last);
|
|
||||||
TRI_ASSERT(found != _enumeratedPath.vertices.end()); // We have to find it once, it is at least the last!
|
|
||||||
if ((++found) != _enumeratedPath.vertices.end()) {
|
|
||||||
// Test if we found the last element. That is ok.
|
|
||||||
prune();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
// Vertex Invalid. Revoke edge
|
||||||
if (_enumeratedPath.edges.empty()) {
|
|
||||||
// We are done with enumerating paths
|
|
||||||
_enumeratedPath.edges.clear();
|
|
||||||
_enumeratedPath.vertices.clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// This either modifies the stack or _lastEdges is empty.
|
|
||||||
// This will return in next depth
|
|
||||||
prune();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DepthFirstEnumerator::prune() {
|
|
||||||
if (!_lastEdges.empty()) {
|
|
||||||
_lastEdges.pop();
|
|
||||||
_lastEdgesIdx.pop();
|
|
||||||
if (!_enumeratedPath.edges.empty()) {
|
|
||||||
_enumeratedPath.edges.pop_back();
|
_enumeratedPath.edges.pop_back();
|
||||||
_enumeratedPath.vertices.pop_back();
|
} else {
|
||||||
|
// cursor is empty.
|
||||||
|
_edgeCursors.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If we get here all cursors are exhausted.
|
||||||
|
_enumeratedPath.edges.clear();
|
||||||
|
_enumeratedPath.vertices.clear();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
arangodb::aql::AqlValue DepthFirstEnumerator::lastVertexToAqlValue() {
|
arangodb::aql::AqlValue DepthFirstEnumerator::lastVertexToAqlValue() {
|
||||||
|
@ -137,7 +112,7 @@ arangodb::aql::AqlValue DepthFirstEnumerator::pathToAqlValue(arangodb::velocypac
|
||||||
}
|
}
|
||||||
|
|
||||||
BreadthFirstEnumerator::BreadthFirstEnumerator(Traverser* traverser,
|
BreadthFirstEnumerator::BreadthFirstEnumerator(Traverser* traverser,
|
||||||
std::string const& startVertex,
|
VPackSlice startVertex,
|
||||||
TraverserOptions const* opts)
|
TraverserOptions const* opts)
|
||||||
: PathEnumerator(traverser, startVertex, opts),
|
: PathEnumerator(traverser, startVertex, opts),
|
||||||
_schreierIndex(1),
|
_schreierIndex(1),
|
||||||
|
@ -213,10 +188,10 @@ bool BreadthFirstEnumerator::next() {
|
||||||
bool shouldReturnPath = _currentDepth + 1 >= _opts->minDepth;
|
bool shouldReturnPath = _currentDepth + 1 >= _opts->minDepth;
|
||||||
if (!_tmpEdges.empty()) {
|
if (!_tmpEdges.empty()) {
|
||||||
bool didInsert = false;
|
bool didInsert = false;
|
||||||
std::string v;
|
VPackSlice v;
|
||||||
for (auto const& e : _tmpEdges) {
|
for (auto const& e : _tmpEdges) {
|
||||||
bool valid =
|
bool valid =
|
||||||
_traverser->getVertex(e, nextVertex, _currentDepth, v);
|
_traverser->getSingleVertex(e, nextVertex, _currentDepth, v);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
auto step = std::make_unique<PathStep>(nextIdx, e, v);
|
auto step = std::make_unique<PathStep>(nextIdx, e, v);
|
||||||
_schreier.emplace_back(step.get());
|
_schreier.emplace_back(step.get());
|
||||||
|
@ -251,12 +226,6 @@ bool BreadthFirstEnumerator::next() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreadthFirstEnumerator::prune() {
|
|
||||||
if (!_nextDepth.empty()) {
|
|
||||||
_nextDepth.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Optimize this. Remove enumeratedPath
|
// TODO Optimize this. Remove enumeratedPath
|
||||||
// All can be read from schreier vector directly
|
// All can be read from schreier vector directly
|
||||||
arangodb::aql::AqlValue BreadthFirstEnumerator::lastVertexToAqlValue() {
|
arangodb::aql::AqlValue BreadthFirstEnumerator::lastVertexToAqlValue() {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#define ARANGODB_VOCBASE_PATHENUMERATOR_H 1
|
#define ARANGODB_VOCBASE_PATHENUMERATOR_H 1
|
||||||
|
|
||||||
#include "Basics/Common.h"
|
#include "Basics/Common.h"
|
||||||
|
#include <velocypack/Slice.h>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
|
@ -37,12 +38,13 @@ class Builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace traverser {
|
namespace traverser {
|
||||||
|
class EdgeCursor;
|
||||||
class Traverser;
|
class Traverser;
|
||||||
struct TraverserOptions;
|
struct TraverserOptions;
|
||||||
|
|
||||||
struct EnumeratedPath {
|
struct EnumeratedPath {
|
||||||
std::vector<std::string> edges;
|
std::vector<arangodb::velocypack::Slice> edges;
|
||||||
std::vector<std::string> vertices;
|
std::vector<arangodb::velocypack::Slice> vertices;
|
||||||
EnumeratedPath() {}
|
EnumeratedPath() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,7 +81,7 @@ class PathEnumerator {
|
||||||
EnumeratedPath _enumeratedPath;
|
EnumeratedPath _enumeratedPath;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PathEnumerator(Traverser* traverser, std::string const& startVertex,
|
PathEnumerator(Traverser* traverser, arangodb::velocypack::Slice startVertex,
|
||||||
TraverserOptions const* opts)
|
TraverserOptions const* opts)
|
||||||
: _traverser(traverser), _isFirst(true), _opts(opts) {
|
: _traverser(traverser), _isFirst(true), _opts(opts) {
|
||||||
_enumeratedPath.vertices.push_back(startVertex);
|
_enumeratedPath.vertices.push_back(startVertex);
|
||||||
|
@ -96,13 +98,6 @@ class PathEnumerator {
|
||||||
|
|
||||||
virtual bool next() = 0;
|
virtual bool next() = 0;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief Prunes the current path prefix, the next function should not return
|
|
||||||
/// any path having this prefix anymore.
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
virtual void prune() = 0;
|
|
||||||
|
|
||||||
virtual aql::AqlValue lastVertexToAqlValue() = 0;
|
virtual aql::AqlValue lastVertexToAqlValue() = 0;
|
||||||
virtual aql::AqlValue lastEdgeToAqlValue() = 0;
|
virtual aql::AqlValue lastEdgeToAqlValue() = 0;
|
||||||
virtual aql::AqlValue pathToAqlValue(arangodb::velocypack::Builder&) = 0;
|
virtual aql::AqlValue pathToAqlValue(arangodb::velocypack::Builder&) = 0;
|
||||||
|
@ -111,30 +106,20 @@ class PathEnumerator {
|
||||||
class DepthFirstEnumerator final : public PathEnumerator {
|
class DepthFirstEnumerator final : public PathEnumerator {
|
||||||
private:
|
private:
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief The pointers returned for edge indexes on this path. Used to
|
/// @brief The stack of EdgeCursors to walk through.
|
||||||
/// continue
|
|
||||||
/// the search on respective levels.
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::stack<size_t*> _lastEdges;
|
std::stack<EdgeCursor*> _edgeCursors;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief An internal index for the edge collection used at each depth level
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
std::stack<size_t> _lastEdgesIdx;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DepthFirstEnumerator(
|
DepthFirstEnumerator(Traverser* traverser,
|
||||||
Traverser* traverser,
|
arangodb::velocypack::Slice startVertex,
|
||||||
std::string const& startVertex, TraverserOptions const* opts)
|
TraverserOptions const* opts)
|
||||||
: PathEnumerator(traverser, startVertex, opts) {
|
: PathEnumerator(traverser, startVertex, opts) {}
|
||||||
_lastEdges.push(nullptr);
|
|
||||||
_lastEdgesIdx.push(0);
|
|
||||||
TRI_ASSERT(_lastEdges.size() == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
~DepthFirstEnumerator() {}
|
~DepthFirstEnumerator() {
|
||||||
|
#warning Who is responsible for the cursors? Traverser or this class? Maybe they are just leased.
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Get the next Path element from the traversal.
|
/// @brief Get the next Path element from the traversal.
|
||||||
|
@ -147,8 +132,6 @@ class DepthFirstEnumerator final : public PathEnumerator {
|
||||||
/// any path having this prefix anymore.
|
/// any path having this prefix anymore.
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void prune() override;
|
|
||||||
|
|
||||||
aql::AqlValue lastVertexToAqlValue() override;
|
aql::AqlValue lastVertexToAqlValue() override;
|
||||||
|
|
||||||
aql::AqlValue lastEdgeToAqlValue() override;
|
aql::AqlValue lastEdgeToAqlValue() override;
|
||||||
|
@ -166,17 +149,17 @@ class BreadthFirstEnumerator final : public PathEnumerator {
|
||||||
|
|
||||||
struct PathStep {
|
struct PathStep {
|
||||||
size_t sourceIdx;
|
size_t sourceIdx;
|
||||||
std::string edge;
|
arangodb::velocypack::Slice edge;
|
||||||
std::string vertex;
|
arangodb::velocypack::Slice vertex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PathStep() {}
|
PathStep() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PathStep(std::string const& vertex) : sourceIdx(0), vertex(vertex) {}
|
explicit PathStep(arangodb::velocypack::Slice vertex) : sourceIdx(0), vertex(vertex) {}
|
||||||
|
|
||||||
PathStep(size_t sourceIdx, std::string const& edge,
|
PathStep(size_t sourceIdx, arangodb::velocypack::Slice edge,
|
||||||
std::string const& vertex)
|
arangodb::velocypack::Slice vertex)
|
||||||
: sourceIdx(sourceIdx), edge(edge), vertex(vertex) {}
|
: sourceIdx(sourceIdx), edge(edge), vertex(vertex) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -230,7 +213,7 @@ class BreadthFirstEnumerator final : public PathEnumerator {
|
||||||
/// @brief Vector storing the position at current search depth
|
/// @brief Vector storing the position at current search depth
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::unordered_set<std::string> _tmpEdges;
|
std::unordered_set<arangodb::velocypack::Slice> _tmpEdges;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Marker for the search depth. Used to abort searching.
|
/// @brief Marker for the search depth. Used to abort searching.
|
||||||
|
@ -247,7 +230,8 @@ class BreadthFirstEnumerator final : public PathEnumerator {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BreadthFirstEnumerator(Traverser* traverser,
|
BreadthFirstEnumerator(Traverser* traverser,
|
||||||
std::string const& startVertex, TraverserOptions const* opts);
|
arangodb::velocypack::Slice startVertex,
|
||||||
|
TraverserOptions const* opts);
|
||||||
|
|
||||||
~BreadthFirstEnumerator() {
|
~BreadthFirstEnumerator() {
|
||||||
for (auto& it : _schreier) {
|
for (auto& it : _schreier) {
|
||||||
|
@ -266,8 +250,6 @@ class BreadthFirstEnumerator final : public PathEnumerator {
|
||||||
/// any path having this prefix anymore.
|
/// any path having this prefix anymore.
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void prune() override;
|
|
||||||
|
|
||||||
aql::AqlValue lastVertexToAqlValue() override;
|
aql::AqlValue lastVertexToAqlValue() override;
|
||||||
|
|
||||||
aql::AqlValue lastEdgeToAqlValue() override;
|
aql::AqlValue lastEdgeToAqlValue() override;
|
||||||
|
|
|
@ -56,6 +56,15 @@ static int FetchDocumentById(arangodb::Transaction* trx,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SingleServerEdgeCursor::SingleServerEdgeCursor() {
|
||||||
|
#warning TODO Implement
|
||||||
|
};
|
||||||
|
|
||||||
|
bool SingleServerEdgeCursor::next(std::vector<VPackSlice>& result) {
|
||||||
|
#warning TODO Implement
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
SingleServerTraverser::SingleServerTraverser(TraverserOptions& opts,
|
SingleServerTraverser::SingleServerTraverser(TraverserOptions& opts,
|
||||||
arangodb::Transaction* trx)
|
arangodb::Transaction* trx)
|
||||||
: Traverser(opts), _trx(trx) {
|
: Traverser(opts), _trx(trx) {
|
||||||
|
@ -77,8 +86,9 @@ bool SingleServerTraverser::edgeMatchesConditions(VPackSlice e, size_t depth) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleServerTraverser::vertexMatchesConditions(std::string const& v,
|
bool SingleServerTraverser::vertexMatchesConditions(VPackSlice v,
|
||||||
size_t depth) {
|
size_t depth) {
|
||||||
|
TRI_ASSERT(v.isString());
|
||||||
#warning it is possible to not fetch the vertex if no check is required.
|
#warning it is possible to not fetch the vertex if no check is required.
|
||||||
aql::AqlValue vertex = fetchVertexData(v);
|
aql::AqlValue vertex = fetchVertexData(v);
|
||||||
if (!_opts.evaluateVertexExpression(vertex.slice(), depth)) {
|
if (!_opts.evaluateVertexExpression(vertex.slice(), depth)) {
|
||||||
|
@ -88,12 +98,14 @@ bool SingleServerTraverser::vertexMatchesConditions(std::string const& v,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
aql::AqlValue SingleServerTraverser::fetchVertexData(std::string const& id) {
|
aql::AqlValue SingleServerTraverser::fetchVertexData(VPackSlice id) {
|
||||||
|
TRI_ASSERT(id.isString());
|
||||||
auto it = _vertices.find(id);
|
auto it = _vertices.find(id);
|
||||||
|
|
||||||
if (it == _vertices.end()) {
|
if (it == _vertices.end()) {
|
||||||
TRI_doc_mptr_t mptr;
|
TRI_doc_mptr_t mptr;
|
||||||
int res = FetchDocumentById(_trx, id, &mptr);
|
#warning Do we need the copy here
|
||||||
|
int res = FetchDocumentById(_trx, id.copyString(), &mptr);
|
||||||
++_readDocuments;
|
++_readDocuments;
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
return aql::AqlValue(basics::VelocyPackHelper::NullValue());
|
return aql::AqlValue(basics::VelocyPackHelper::NullValue());
|
||||||
|
@ -107,20 +119,26 @@ aql::AqlValue SingleServerTraverser::fetchVertexData(std::string const& id) {
|
||||||
return aql::AqlValue((*it).second, aql::AqlValueFromMasterPointer());
|
return aql::AqlValue((*it).second, aql::AqlValueFromMasterPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
aql::AqlValue SingleServerTraverser::fetchEdgeData(std::string const& id) {
|
aql::AqlValue SingleServerTraverser::fetchEdgeData(VPackSlice edge) {
|
||||||
|
#warning Is this enough?
|
||||||
|
return aql::AqlValue(edge);
|
||||||
|
/*
|
||||||
auto it = _edges.find(id);
|
auto it = _edges.find(id);
|
||||||
|
|
||||||
TRI_ASSERT(it != _edges.end());
|
TRI_ASSERT(it != _edges.end());
|
||||||
return aql::AqlValue((*it).second, aql::AqlValueFromMasterPointer());
|
return aql::AqlValue((*it).second, aql::AqlValueFromMasterPointer());
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleServerTraverser::addVertexToVelocyPack(std::string const& id,
|
void SingleServerTraverser::addVertexToVelocyPack(VPackSlice id,
|
||||||
arangodb::velocypack::Builder& result) {
|
VPackBuilder& result) {
|
||||||
|
TRI_ASSERT(id.isString());
|
||||||
auto it = _vertices.find(id);
|
auto it = _vertices.find(id);
|
||||||
|
|
||||||
if (it == _vertices.end()) {
|
if (it == _vertices.end()) {
|
||||||
TRI_doc_mptr_t mptr;
|
TRI_doc_mptr_t mptr;
|
||||||
int res = FetchDocumentById(_trx, id, &mptr);
|
#warning Do we need the copy here?
|
||||||
|
int res = FetchDocumentById(_trx, id.copyString(), &mptr);
|
||||||
++_readDocuments;
|
++_readDocuments;
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
result.add(basics::VelocyPackHelper::NullValue());
|
result.add(basics::VelocyPackHelper::NullValue());
|
||||||
|
@ -134,62 +152,106 @@ void SingleServerTraverser::addVertexToVelocyPack(std::string const& id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleServerTraverser::addEdgeToVelocyPack(std::string const& id,
|
void SingleServerTraverser::addEdgeToVelocyPack(VPackSlice edge,
|
||||||
arangodb::velocypack::Builder& result) {
|
VPackBuilder& result) {
|
||||||
auto it = _edges.find(id);
|
result.addExternal(edge.begin());
|
||||||
|
|
||||||
TRI_ASSERT(it != _edges.end());
|
|
||||||
result.addExternal((*it).second);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleServerTraverser::VertexGetter::getVertex(std::string const& edge,
|
bool SingleServerTraverser::VertexGetter::getVertex(
|
||||||
std::string const& vertex,
|
VPackSlice edge, std::vector<VPackSlice>& result) {
|
||||||
size_t depth,
|
VPackSlice cmp = result.back();
|
||||||
std::string& result) {
|
VPackSlice from = Transaction::extractFromFromDocument(edge);
|
||||||
auto it = _traverser->_edges.find(edge);
|
#warning Here we have to execute VertexFilter
|
||||||
TRI_ASSERT(it != _traverser->_edges.end());
|
/// If the vertex is not cached in _traverser->_vertices => incr. _filteredPath return false;
|
||||||
VPackSlice v((*it).second);
|
/// Else check condition if ok => return true, else return false.
|
||||||
// NOTE: We assume that we only have valid edges.
|
/// When returning false set result = ""
|
||||||
VPackSlice from = Transaction::extractFromFromDocument(v);
|
if (arangodb::basics::VelocyPackHelper::compare(cmp, from, false) != 0) {
|
||||||
if (from.isEqualString(vertex)) {
|
result.emplace_back(from);
|
||||||
result = Transaction::extractToFromDocument(v).copyString();
|
|
||||||
} else {
|
} else {
|
||||||
result = from.copyString();
|
result.emplace_back(Transaction::extractToFromDocument(edge));
|
||||||
}
|
|
||||||
if (!_traverser->vertexMatchesConditions(result, depth)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleServerTraverser::VertexGetter::reset(std::string const&) {
|
bool SingleServerTraverser::VertexGetter::getSingleVertex(VPackSlice edge,
|
||||||
|
VPackSlice cmp,
|
||||||
|
size_t depth,
|
||||||
|
VPackSlice& result) {
|
||||||
|
VPackSlice from = Transaction::extractFromFromDocument(edge);
|
||||||
|
#warning Here we have to execute VertexFilter
|
||||||
|
/// If the vertex is not cached in _traverser->_vertices => incr. _filteredPath return false;
|
||||||
|
/// Else check condition if ok => return true, else return false.
|
||||||
|
/// When returning false set result = ""
|
||||||
|
if (arangodb::basics::VelocyPackHelper::compare(cmp, from, false) != 0) {
|
||||||
|
result = from;
|
||||||
|
} else {
|
||||||
|
result = Transaction::extractToFromDocument(edge);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void SingleServerTraverser::VertexGetter::reset(arangodb::velocypack::Slice) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleServerTraverser::UniqueVertexGetter::getVertex(
|
bool SingleServerTraverser::UniqueVertexGetter::getVertex(
|
||||||
std::string const& edge, std::string const& vertex, size_t depth,
|
VPackSlice edge, std::vector<VPackSlice>& result) {
|
||||||
std::string& result) {
|
VPackSlice toAdd = Transaction::extractFromFromDocument(edge);
|
||||||
|
VPackSlice cmp = result.back();
|
||||||
|
|
||||||
|
if (arangodb::basics::VelocyPackHelper::compare(toAdd, cmp, false) == 0) {
|
||||||
|
toAdd = Transaction::extractToFromDocument(edge);
|
||||||
|
}
|
||||||
|
|
||||||
auto it = _traverser->_edges.find(edge);
|
#warning Here we have to execute VertexFilter
|
||||||
TRI_ASSERT(it != _traverser->_edges.end());
|
/// If the vertex is not cached in _traverser->_vertices => incr. _filteredPath return false;
|
||||||
VPackSlice v((*it).second);
|
/// Else check condition if ok => return true, else return false.
|
||||||
// NOTE: We assume that we only have valid edges.
|
/// When returning false set result = ""
|
||||||
VPackSlice from = Transaction::extractFromFromDocument(v);
|
/// When returning true: _returnedVertices.emplace(result)
|
||||||
if (from.isEqualString(vertex)) {
|
|
||||||
result = Transaction::extractToFromDocument(v).copyString();
|
if (_returnedVertices.find(toAdd) != _returnedVertices.end()) {
|
||||||
|
// This vertex is not unique.
|
||||||
|
++_traverser->_filteredPaths;
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
result = from.copyString();
|
_returnedVertices.emplace(toAdd);
|
||||||
|
result.emplace_back(toAdd);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (_returnedVertices.find(result) != _returnedVertices.end()) {
|
|
||||||
return false;
|
// This should never be reached
|
||||||
}
|
return false;
|
||||||
if (!_traverser->vertexMatchesConditions(result, depth)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_returnedVertices.emplace(result);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleServerTraverser::UniqueVertexGetter::reset(std::string const& startVertex) {
|
bool SingleServerTraverser::UniqueVertexGetter::getSingleVertex(
|
||||||
|
VPackSlice edge, VPackSlice cmp, size_t depth, VPackSlice& result) {
|
||||||
|
result = Transaction::extractFromFromDocument(edge);
|
||||||
|
|
||||||
|
if (arangodb::basics::VelocyPackHelper::compare(result, cmp, false) == 0) {
|
||||||
|
result = Transaction::extractToFromDocument(edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
#warning Here we have to execute VertexFilter
|
||||||
|
/// If the vertex is not cached in _traverser->_vertices => incr. _filteredPath return false;
|
||||||
|
/// Else check condition if ok => return true, else return false.
|
||||||
|
/// When returning false set result = ""
|
||||||
|
/// When returning true: _returnedVertices.emplace(result)
|
||||||
|
|
||||||
|
if (_returnedVertices.find(result) != _returnedVertices.end()) {
|
||||||
|
// This vertex is not unique.
|
||||||
|
++_traverser->_filteredPaths;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
_returnedVertices.emplace(result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should never be reached
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleServerTraverser::UniqueVertexGetter::reset(VPackSlice startVertex) {
|
||||||
_returnedVertices.clear();
|
_returnedVertices.clear();
|
||||||
// The startVertex always counts as visited!
|
// The startVertex always counts as visited!
|
||||||
_returnedVertices.emplace(startVertex);
|
_returnedVertices.emplace(startVertex);
|
||||||
|
@ -198,6 +260,11 @@ void SingleServerTraverser::UniqueVertexGetter::reset(std::string const& startVe
|
||||||
void SingleServerTraverser::setStartVertex(std::string const& v) {
|
void SingleServerTraverser::setStartVertex(std::string const& v) {
|
||||||
_pruneNext = false;
|
_pruneNext = false;
|
||||||
|
|
||||||
|
#warning Who is responsible for this builder?!
|
||||||
|
VPackBuilder tmp;
|
||||||
|
tmp.add(VPackValue(v));
|
||||||
|
VPackSlice idSlice = tmp.slice();
|
||||||
|
|
||||||
TRI_doc_mptr_t vertex;
|
TRI_doc_mptr_t vertex;
|
||||||
int result = FetchDocumentById(_trx, v, &vertex);
|
int result = FetchDocumentById(_trx, v, &vertex);
|
||||||
++_readDocuments;
|
++_readDocuments;
|
||||||
|
@ -207,19 +274,19 @@ void SingleServerTraverser::setStartVertex(std::string const& v) {
|
||||||
_done = true;
|
_done = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
VPackSlice vertexSlice(vertex.vpack());
|
||||||
|
|
||||||
_vertices.emplace(v, vertex.vpack());
|
if (!_opts.evaluateVertexExpression(vertexSlice, 0)) {
|
||||||
if (!_opts.evaluateVertexExpression(VPackSlice(vertex.vpack()), 0)) {
|
|
||||||
// Start vertex invalid
|
// Start vertex invalid
|
||||||
++_filteredPaths;
|
++_filteredPaths;
|
||||||
_done = true;
|
_done = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_vertexGetter->reset(v);
|
_vertexGetter->reset(idSlice);
|
||||||
if (_opts.useBreadthFirst) {
|
if (_opts.useBreadthFirst) {
|
||||||
_enumerator.reset(new BreadthFirstEnumerator(this, v, &_opts));
|
_enumerator.reset(new BreadthFirstEnumerator(this, vertexSlice, &_opts));
|
||||||
} else {
|
} else {
|
||||||
_enumerator.reset(new DepthFirstEnumerator(this, v, &_opts));
|
_enumerator.reset(new DepthFirstEnumerator(this, vertexSlice, &_opts));
|
||||||
}
|
}
|
||||||
_done = false;
|
_done = false;
|
||||||
}
|
}
|
||||||
|
@ -229,26 +296,25 @@ void SingleServerTraverser::getEdge(std::string const& startVertex,
|
||||||
size_t*& last, size_t& eColIdx) {
|
size_t*& last, size_t& eColIdx) {
|
||||||
return _edgeGetter->getEdge(startVertex, edges, last, eColIdx);
|
return _edgeGetter->getEdge(startVertex, edges, last, eColIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleServerTraverser::getAllEdges(
|
void SingleServerTraverser::getAllEdges(
|
||||||
std::string const& startVertex, std::unordered_set<std::string>& edges,
|
arangodb::velocypack::Slice startVertex,
|
||||||
size_t depth) {
|
std::unordered_set<arangodb::velocypack::Slice>& edges, size_t depth) {
|
||||||
return _edgeGetter->getAllEdges(startVertex, edges, depth);
|
return _edgeGetter->getAllEdges(startVertex, edges, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleServerTraverser::getVertex(std::string const& edge,
|
bool SingleServerTraverser::getVertex(VPackSlice edge,
|
||||||
std::string const& vertex, size_t depth,
|
std::vector<VPackSlice>& result) {
|
||||||
std::string& result) {
|
return _vertexGetter->getVertex(edge, result);
|
||||||
return _vertexGetter->getVertex(edge, vertex, depth, result);
|
}
|
||||||
|
|
||||||
|
bool SingleServerTraverser::getSingleVertex(VPackSlice edge, VPackSlice vertex,
|
||||||
|
size_t depth, VPackSlice& result) {
|
||||||
|
return _vertexGetter->getSingleVertex(edge, vertex, depth, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleServerTraverser::next() {
|
bool SingleServerTraverser::next() {
|
||||||
TRI_ASSERT(!_done);
|
TRI_ASSERT(!_done);
|
||||||
if (_pruneNext) {
|
|
||||||
_pruneNext = false;
|
|
||||||
_enumerator->prune();
|
|
||||||
}
|
|
||||||
TRI_ASSERT(!_pruneNext);
|
|
||||||
bool res = _enumerator->next();
|
bool res = _enumerator->next();
|
||||||
if (!res) {
|
if (!res) {
|
||||||
_done = true;
|
_done = true;
|
||||||
|
@ -425,9 +491,8 @@ void SingleServerTraverser::EdgeGetter::getEdge(std::string const& startVertex,
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleServerTraverser::EdgeGetter::getAllEdges(
|
void SingleServerTraverser::EdgeGetter::getAllEdges(
|
||||||
std::string const& startVertex, std::unordered_set<std::string>& edges,
|
VPackSlice startVertex, std::unordered_set<VPackSlice>& edges,
|
||||||
size_t depth) {
|
size_t depth) {
|
||||||
|
|
||||||
#warning reimplement
|
#warning reimplement
|
||||||
/*
|
/*
|
||||||
size_t idxId = 0;
|
size_t idxId = 0;
|
||||||
|
|
|
@ -37,8 +37,20 @@ namespace traverser {
|
||||||
|
|
||||||
class PathEnumerator;
|
class PathEnumerator;
|
||||||
|
|
||||||
class SingleServerTraverser final : public Traverser {
|
class SingleServerEdgeCursor : public EdgeCursor {
|
||||||
|
private:
|
||||||
|
std::vector<OperationCursor> _cursors;
|
||||||
|
size_t _currentCursor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SingleServerEdgeCursor();
|
||||||
|
|
||||||
|
~SingleServerEdgeCursor() {}
|
||||||
|
|
||||||
|
bool next(std::vector<arangodb::velocypack::Slice>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
class SingleServerTraverser final : public Traverser {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
class VertexGetter {
|
class VertexGetter {
|
||||||
|
@ -48,9 +60,14 @@ class SingleServerTraverser final : public Traverser {
|
||||||
|
|
||||||
virtual ~VertexGetter() = default;
|
virtual ~VertexGetter() = default;
|
||||||
|
|
||||||
virtual bool getVertex(std::string const&, std::string const&, size_t,
|
virtual bool getVertex(arangodb::velocypack::Slice,
|
||||||
std::string&);
|
std::vector<arangodb::velocypack::Slice>&);
|
||||||
virtual void reset(std::string const&);
|
|
||||||
|
virtual bool getSingleVertex(arangodb::velocypack::Slice,
|
||||||
|
arangodb::velocypack::Slice, size_t,
|
||||||
|
arangodb::velocypack::Slice&);
|
||||||
|
|
||||||
|
virtual void reset(arangodb::velocypack::Slice);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SingleServerTraverser* _traverser;
|
SingleServerTraverser* _traverser;
|
||||||
|
@ -63,13 +80,17 @@ class SingleServerTraverser final : public Traverser {
|
||||||
|
|
||||||
~UniqueVertexGetter() = default;
|
~UniqueVertexGetter() = default;
|
||||||
|
|
||||||
bool getVertex(std::string const&, std::string const&, size_t,
|
bool getVertex(arangodb::velocypack::Slice,
|
||||||
std::string&) override;
|
std::vector<arangodb::velocypack::Slice>&) override;
|
||||||
|
|
||||||
void reset(std::string const&) override;
|
bool getSingleVertex(arangodb::velocypack::Slice,
|
||||||
|
arangodb::velocypack::Slice, size_t,
|
||||||
|
arangodb::velocypack::Slice&) override;
|
||||||
|
|
||||||
|
void reset(arangodb::velocypack::Slice) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_set<std::string> _returnedVertices;
|
std::unordered_set<arangodb::velocypack::Slice> _returnedVertices;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -91,7 +112,8 @@ class SingleServerTraverser final : public Traverser {
|
||||||
void getEdge(std::string const&, std::vector<std::string>&,
|
void getEdge(std::string const&, std::vector<std::string>&,
|
||||||
size_t*&, size_t&);
|
size_t*&, size_t&);
|
||||||
|
|
||||||
void getAllEdges(std::string const&, std::unordered_set<std::string>&, size_t);
|
void getAllEdges(arangodb::velocypack::Slice,
|
||||||
|
std::unordered_set<arangodb::velocypack::Slice>&, size_t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -193,16 +215,22 @@ public:
|
||||||
/// @brief Function to load all edges for a list of nodes
|
/// @brief Function to load all edges for a list of nodes
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void getAllEdges(std::string const&, std::unordered_set<std::string>&,
|
void getAllEdges(arangodb::velocypack::Slice,
|
||||||
|
std::unordered_set<arangodb::velocypack::Slice>&,
|
||||||
size_t) override;
|
size_t) override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief Function to load the other sides vertex of an edge
|
/// @brief Function to load the other sides vertex of an edge
|
||||||
/// Returns true if the vertex passes filtering conditions
|
/// Returns true if the vertex passes filtering conditions
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
/// Adds the _id of the vertex into the given vector
|
||||||
|
|
||||||
bool getVertex(std::string const&, std::string const&, size_t,
|
bool getVertex(arangodb::velocypack::Slice,
|
||||||
std::string&) override;
|
std::vector<arangodb::velocypack::Slice>&) override;
|
||||||
|
|
||||||
|
/// @brief Function to load the other sides vertex of an edge
|
||||||
|
/// Returns true if the vertex passes filtering conditions
|
||||||
|
|
||||||
|
bool getSingleVertex(arangodb::velocypack::Slice, arangodb::velocypack::Slice,
|
||||||
|
size_t depth, arangodb::velocypack::Slice&) override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Get the next possible path in the graph.
|
/// @brief Get the next possible path in the graph.
|
||||||
|
@ -239,32 +267,32 @@ public:
|
||||||
/// @brief Function to fetch the real data of a vertex into an AQLValue
|
/// @brief Function to fetch the real data of a vertex into an AQLValue
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
aql::AqlValue fetchVertexData(std::string const&) override;
|
aql::AqlValue fetchVertexData(arangodb::velocypack::Slice) override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Function to fetch the real data of an edge into an AQLValue
|
/// @brief Function to fetch the real data of an edge into an AQLValue
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
aql::AqlValue fetchEdgeData(std::string const&) override;
|
aql::AqlValue fetchEdgeData(arangodb::velocypack::Slice) override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Function to add the real data of a vertex into a velocypack builder
|
/// @brief Function to add the real data of a vertex into a velocypack builder
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void addVertexToVelocyPack(std::string const&,
|
void addVertexToVelocyPack(arangodb::velocypack::Slice,
|
||||||
arangodb::velocypack::Builder&) override;
|
arangodb::velocypack::Builder&) override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Function to add the real data of an edge into a velocypack builder
|
/// @brief Function to add the real data of an edge into a velocypack builder
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void addEdgeToVelocyPack(std::string const&,
|
void addEdgeToVelocyPack(arangodb::velocypack::Slice,
|
||||||
arangodb::velocypack::Builder&) override;
|
arangodb::velocypack::Builder&) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool edgeMatchesConditions(arangodb::velocypack::Slice, size_t);
|
bool edgeMatchesConditions(arangodb::velocypack::Slice, size_t);
|
||||||
|
|
||||||
bool vertexMatchesConditions(std::string const&, size_t);
|
bool vertexMatchesConditions(arangodb::velocypack::Slice, size_t);
|
||||||
|
|
||||||
std::vector<TRI_document_collection_t*> _edgeCols;
|
std::vector<TRI_document_collection_t*> _edgeCols;
|
||||||
|
|
||||||
|
@ -279,7 +307,7 @@ public:
|
||||||
/// document VPack value (in datafiles)
|
/// document VPack value (in datafiles)
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::unordered_map<std::string, uint8_t const*> _vertices;
|
std::unordered_map<arangodb::velocypack::Slice, uint8_t const*> _vertices;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Cache for edge documents, points from _id to start of edge
|
/// @brief Cache for edge documents, points from _id to start of edge
|
||||||
|
|
|
@ -71,55 +71,6 @@ void arangodb::traverser::ShortestPath::vertexToVelocyPack(Transaction* trx, siz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning TODO remove
|
|
||||||
/*
|
|
||||||
size_t arangodb::traverser::TraverserOptions::collectionCount () const {
|
|
||||||
return _collections.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool arangodb::traverser::TraverserOptions::getCollection(
|
|
||||||
size_t index, std::string& name, TRI_edge_direction_e& dir) const {
|
|
||||||
if (index >= _collections.size()) {
|
|
||||||
// No more collections stop now
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (_directions.size() == 1) {
|
|
||||||
dir = _directions.at(0);
|
|
||||||
} else {
|
|
||||||
dir = _directions.at(index);
|
|
||||||
}
|
|
||||||
name = _collections.at(index);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool arangodb::traverser::TraverserOptions::getCollectionAndSearchValue(
|
|
||||||
size_t index, std::string const& vertexId, std::string& name,
|
|
||||||
Transaction::IndexHandle& indexHandle, VPackBuilder& builder) const {
|
|
||||||
if (index >= _collections.size()) {
|
|
||||||
// No more collections stop now
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
TRI_edge_direction_e dir;
|
|
||||||
TRI_ASSERT(!_directions.empty());
|
|
||||||
if (_directions.size() == 1) {
|
|
||||||
dir = _directions.at(0);
|
|
||||||
} else {
|
|
||||||
dir = _directions.at(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
TRI_ASSERT(!_collections.empty());
|
|
||||||
name = _collections.at(index);
|
|
||||||
|
|
||||||
TRI_ASSERT(!_indexHandles.empty());
|
|
||||||
indexHandle = _indexHandles.at(index);
|
|
||||||
|
|
||||||
builder.clear();
|
|
||||||
arangodb::EdgeIndex::buildSearchValue(dir, vertexId, builder);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool arangodb::traverser::TraverserOptions::evaluateEdgeExpression(arangodb::velocypack::Slice edge, size_t depth) const {
|
bool arangodb::traverser::TraverserOptions::evaluateEdgeExpression(arangodb::velocypack::Slice edge, size_t depth) const {
|
||||||
#warning This has to be implemented.
|
#warning This has to be implemented.
|
||||||
return true;
|
return true;
|
||||||
|
@ -130,6 +81,11 @@ bool arangodb::traverser::TraverserOptions::evaluateVertexExpression(arangodb::v
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arangodb::traverser::EdgeCursor* arangodb::traverser::TraverserOptions::nextCursor(VPackSlice vertex, size_t depth) const {
|
||||||
|
#warning This has to be implemented.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Creates an expression from a VelocyPackSlice
|
/// @brief Creates an expression from a VelocyPackSlice
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -41,10 +41,24 @@ class Slice;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace aql {
|
namespace aql {
|
||||||
|
struct AstNode;
|
||||||
class TraversalNode;
|
class TraversalNode;
|
||||||
}
|
}
|
||||||
namespace traverser {
|
namespace traverser {
|
||||||
|
|
||||||
|
/// @brief Abstract class used in the traversals
|
||||||
|
/// to abstract away access to indexes / DBServers.
|
||||||
|
/// Returns edges as VelocyPack.
|
||||||
|
|
||||||
|
class EdgeCursor {
|
||||||
|
public:
|
||||||
|
EdgeCursor() {}
|
||||||
|
virtual ~EdgeCursor() {}
|
||||||
|
|
||||||
|
virtual bool next(std::vector<arangodb::velocypack::Slice>&) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#warning Deprecated
|
||||||
class TraverserExpression {
|
class TraverserExpression {
|
||||||
public:
|
public:
|
||||||
bool isEdgeAccess;
|
bool isEdgeAccess;
|
||||||
|
@ -207,11 +221,11 @@ struct TraverserOptions {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
arangodb::Transaction* _trx;
|
arangodb::Transaction* _trx;
|
||||||
std::vector<std::string> _collections;
|
|
||||||
std::vector<TRI_edge_direction_e> _directions;
|
|
||||||
std::vector<arangodb::Transaction::IndexHandle> _baseIndexHandles;
|
std::vector<arangodb::Transaction::IndexHandle> _baseIndexHandles;
|
||||||
std::unordered_map<size_t, std::vector<arangodb::Transaction::IndexHandle>>
|
std::vector<aql::AstNode const*> _baseConditions;
|
||||||
_depthIndexHandles;
|
std::unordered_map<size_t,
|
||||||
|
std::pair<std::vector<arangodb::Transaction::IndexHandle>,
|
||||||
|
std::vector<aql::AstNode const*>>> _depthIndexHandles;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint64_t minDepth;
|
uint64_t minDepth;
|
||||||
|
@ -235,19 +249,11 @@ struct TraverserOptions {
|
||||||
uniqueEdges(UniquenessLevel::PATH) {
|
uniqueEdges(UniquenessLevel::PATH) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
size_t collectionCount() const;
|
|
||||||
|
|
||||||
bool getCollection(size_t, std::string&, TRI_edge_direction_e&) const;
|
|
||||||
|
|
||||||
bool getCollectionAndSearchValue(size_t, std::string const&, std::string&,
|
|
||||||
arangodb::Transaction::IndexHandle&,
|
|
||||||
arangodb::velocypack::Builder&) const;
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool evaluateEdgeExpression(arangodb::velocypack::Slice, size_t) const;
|
bool evaluateEdgeExpression(arangodb::velocypack::Slice, size_t) const;
|
||||||
|
|
||||||
bool evaluateVertexExpression(arangodb::velocypack::Slice, size_t) const;
|
bool evaluateVertexExpression(arangodb::velocypack::Slice, size_t) const;
|
||||||
|
|
||||||
|
EdgeCursor* nextCursor(arangodb::velocypack::Slice, size_t) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Traverser {
|
class Traverser {
|
||||||
|
@ -313,17 +319,24 @@ class Traverser {
|
||||||
/// @brief Function to load all edges for a list of nodes
|
/// @brief Function to load all edges for a list of nodes
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual void getAllEdges(std::string const&, std::unordered_set<std::string>&,
|
virtual void getAllEdges(arangodb::velocypack::Slice,
|
||||||
|
std::unordered_set<arangodb::velocypack::Slice>&,
|
||||||
size_t) = 0;
|
size_t) = 0;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief Function to load the other sides vertex of an edge
|
/// @brief Function to load the other sides vertex of an edge
|
||||||
/// Returns true if the vertex passes filtering conditions
|
/// Returns true if the vertex passes filtering conditions
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
/// Also apppends the _id value of the vertex in the given vector
|
||||||
|
|
||||||
virtual bool getVertex(std::string const&, std::string const&, size_t,
|
virtual bool getVertex(arangodb::velocypack::Slice,
|
||||||
std::string&) = 0;
|
std::vector<arangodb::velocypack::Slice>&) = 0;
|
||||||
|
|
||||||
|
/// @brief Function to load the other sides vertex of an edge
|
||||||
|
/// Returns true if the vertex passes filtering conditions
|
||||||
|
|
||||||
|
virtual bool getSingleVertex(arangodb::velocypack::Slice,
|
||||||
|
arangodb::velocypack::Slice, size_t,
|
||||||
|
arangodb::velocypack::Slice&) = 0;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Builds only the last vertex as AQLValue
|
/// @brief Builds only the last vertex as AQLValue
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -419,26 +432,26 @@ class Traverser {
|
||||||
/// @brief Function to fetch the real data of a vertex into an AQLValue
|
/// @brief Function to fetch the real data of a vertex into an AQLValue
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual aql::AqlValue fetchVertexData(std::string const&) = 0;
|
virtual aql::AqlValue fetchVertexData(arangodb::velocypack::Slice) = 0;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Function to fetch the real data of an edge into an AQLValue
|
/// @brief Function to fetch the real data of an edge into an AQLValue
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual aql::AqlValue fetchEdgeData(std::string const&) = 0;
|
virtual aql::AqlValue fetchEdgeData(arangodb::velocypack::Slice) = 0;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Function to add the real data of a vertex into a velocypack builder
|
/// @brief Function to add the real data of a vertex into a velocypack builder
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual void addVertexToVelocyPack(std::string const&,
|
virtual void addVertexToVelocyPack(arangodb::velocypack::Slice,
|
||||||
arangodb::velocypack::Builder&) = 0;
|
arangodb::velocypack::Builder&) = 0;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Function to add the real data of an edge into a velocypack builder
|
/// @brief Function to add the real data of an edge into a velocypack builder
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual void addEdgeToVelocyPack(std::string const&,
|
virtual void addEdgeToVelocyPack(arangodb::velocypack::Slice,
|
||||||
arangodb::velocypack::Builder&) = 0;
|
arangodb::velocypack::Builder&) = 0;
|
||||||
};
|
};
|
||||||
} // traverser
|
} // traverser
|
||||||
|
|
Loading…
Reference in New Issue