mirror of https://gitee.com/bigwinds/arangodb
Add support in AQL for smart edge collections in traversals.
This commit is contained in:
parent
295ddba918
commit
154e3c86fc
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue