1
0
Fork 0

Add support in AQL for smart edge collections in traversals.

This commit is contained in:
Max Neunhoeffer 2016-09-29 10:57:49 +02:00
parent 295ddba918
commit 154e3c86fc
4 changed files with 76 additions and 15 deletions

View File

@ -30,6 +30,7 @@
#include "Basics/Exceptions.h"
#include "Basics/StringUtils.h"
#include "Basics/tri-strings.h"
#include "Cluster/ClusterInfo.h"
#include "Utils/CollectionNameResolver.h"
#include "VocBase/LogicalCollection.h"
@ -1438,8 +1439,17 @@ void Ast::injectBindParameters(BindParameters& parameters) {
_query->collections()->add(n, TRI_TRANSACTION_READ);
}
auto eColls = graph->edgeCollections();
auto ci = ClusterInfo::instance();
for (const auto& n : eColls) {
_query->collections()->add(n, TRI_TRANSACTION_READ);
auto c = ci->getCollection(_query->vocbase()->name(), n);
if (!c->isSmart()) {
_query->collections()->add(n, TRI_TRANSACTION_READ);
} else {
// This is only enterprise:
_query->collections()->add("_local_" + n, TRI_TRANSACTION_READ);
_query->collections()->add("_from_" + n, TRI_TRANSACTION_READ);
_query->collections()->add("_to_" + n, TRI_TRANSACTION_READ);
}
}
}
} else if (node->type == NODE_TYPE_SHORTEST_PATH) {
@ -1454,8 +1464,17 @@ void Ast::injectBindParameters(BindParameters& parameters) {
_query->collections()->add(n, TRI_TRANSACTION_READ);
}
auto eColls = graph->edgeCollections();
auto ci = ClusterInfo::instance();
for (const auto& n : eColls) {
_query->collections()->add(n, TRI_TRANSACTION_READ);
auto c = ci->getCollection(_query->vocbase()->name(), n);
if (!c->isSmart()) {
_query->collections()->add(n, TRI_TRANSACTION_READ);
} else {
// This is only enterprise:
_query->collections()->add("_local_" + n, TRI_TRANSACTION_READ);
_query->collections()->add("_from_" + n, TRI_TRANSACTION_READ);
_query->collections()->add("_to_" + n, TRI_TRANSACTION_READ);
}
}
}
}

View File

@ -27,6 +27,7 @@
#include "Basics/Common.h"
#include "VocBase/transaction.h"
#include "VocBase/vocbase.h"
#include "VocBase/LogicalCollection.h"
namespace arangodb {
namespace aql {
@ -83,6 +84,11 @@ struct Collection {
/// @brief set the underlying collection
void setCollection(arangodb::LogicalCollection* coll) { collection = coll; }
/// @brief check smartness of the underlying collection
bool isSmart() const {
return collection != nullptr && collection->isSmart();
}
private:
arangodb::LogicalCollection* collection;

View File

@ -143,7 +143,8 @@ TraversalNode::TraversalNode(ExecutionPlan* plan, size_t id,
_tmpIdNode(_plan->getAst()->createNodeValueString("", 0)),
_fromCondition(nullptr),
_toCondition(nullptr),
_optionsBuild(false) {
_optionsBuild(false),
_isSmart(false) {
TRI_ASSERT(_vocbase != nullptr);
TRI_ASSERT(direction != nullptr);
TRI_ASSERT(start != nullptr);
@ -260,11 +261,28 @@ TraversalNode::TraversalNode(ExecutionPlan* plan, size_t id,
if (length == 0) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_GRAPH_EMPTY);
}
if (baseDirection == TRI_EDGE_ANY) {
_edgeColls.reserve(2 * length);
_directions.reserve(2 * length);
for (const auto& n : eColls) {
// First determine whether all edge collections are smart and sharded
// like a common collection:
_isSmart = true;
std::string distributeShardsLike;
auto ci = ClusterInfo::instance();
for (auto const& n : eColls) {
auto c = ci->getCollection(_vocbase->name(), n);
if (!c->isSmart() || c->distributeShardsLike().empty()) {
_isSmart = false;
break;
}
if (distributeShardsLike.empty()) {
distributeShardsLike = c->distributeShardsLike().empty();
} else if (distributeShardsLike != c->distributeShardsLike()) {
_isSmart = false;
break;
}
}
auto addEdgeColl = [&](std::string const& n) -> void {
if (baseDirection == TRI_EDGE_ANY) {
_directions.emplace_back(TRI_EDGE_OUT);
_edgeColls.emplace_back(std::make_unique<aql::Collection>(
n, _vocbase, TRI_TRANSACTION_READ));
@ -272,17 +290,26 @@ TraversalNode::TraversalNode(ExecutionPlan* plan, size_t id,
_directions.emplace_back(TRI_EDGE_IN);
_edgeColls.emplace_back(std::make_unique<aql::Collection>(
n, _vocbase, TRI_TRANSACTION_READ));
}
} else {
_edgeColls.reserve(length);
_directions.reserve(length);
for (const auto& n : eColls) {
} else {
_edgeColls.emplace_back(std::make_unique<aql::Collection>(
n, _vocbase, TRI_TRANSACTION_READ));
_directions.emplace_back(baseDirection);
}
};
for (const auto& n : eColls) {
auto c = ci->getCollection(_vocbase->name(), n);
if (!c->isSmart()) {
addEdgeColl(n);
} else {
addEdgeColl("_local_" + n);
addEdgeColl("_from_" + n);
if (_isSmart) {
addEdgeColl("_to_" + n);
}
}
}
auto vColls = _graphObj->vertexCollections();
length = vColls.size();
if (length == 0) {
@ -345,7 +372,8 @@ TraversalNode::TraversalNode(
_condition(nullptr),
_fromCondition(nullptr),
_toCondition(nullptr),
_optionsBuild(false) {
_optionsBuild(false),
_isSmart(false) {
_options.reset(options.release());
_graphInfo.openArray();
@ -382,7 +410,8 @@ TraversalNode::TraversalNode(ExecutionPlan* plan,
_tmpIdNode(nullptr),
_fromCondition(nullptr),
_toCondition(nullptr),
_optionsBuild(false) {
_optionsBuild(false),
_isSmart(false) {
VPackSlice dirList = base.get("directions");
for (auto const& it : VPackArrayIterator(dirList)) {

View File

@ -100,6 +100,11 @@ class TraversalNode : public ExecutionNode {
/// @brief return the type of the node
NodeType getType() const override final { return TRAVERSAL; }
/// @brief flag, ob smart traversal (enterprise edition only!) is done
bool isSmart() const {
return _isSmart;
}
/// @brief export to VelocyPack
void toVelocyPackHelper(arangodb::velocypack::Builder&,
bool) const override final;
@ -345,6 +350,8 @@ class TraversalNode : public ExecutionNode {
/// @brief The list of traverser engines grouped by server.
std::unordered_map<ServerID, traverser::TraverserEngineID> _engines;
/// @brief flag, if traversal is smart (enterprise edition only!)
bool _isSmart;
};
} // namespace arangodb::aql