mirror of https://gitee.com/bigwinds/arangodb
(K_)SHORTEST PATHS: Display correct directions in explainer/profiler (#9080)
This commit is contained in:
parent
de9ef00896
commit
73ac4f194d
|
@ -41,10 +41,7 @@ using namespace arangodb::aql;
|
|||
using namespace arangodb::graph;
|
||||
using namespace arangodb::traverser;
|
||||
|
||||
static TRI_edge_direction_e parseDirection(AstNode const* node) {
|
||||
TRI_ASSERT(node->isIntValue());
|
||||
auto dirNum = node->getIntValue();
|
||||
|
||||
static TRI_edge_direction_e uint64ToDirection(uint64_t dirNum) {
|
||||
switch (dirNum) {
|
||||
case 0:
|
||||
return TRI_EDGE_ANY;
|
||||
|
@ -59,6 +56,13 @@ static TRI_edge_direction_e parseDirection(AstNode const* node) {
|
|||
}
|
||||
}
|
||||
|
||||
static TRI_edge_direction_e parseDirection(AstNode const* node) {
|
||||
TRI_ASSERT(node->isIntValue());
|
||||
auto dirNum = node->getIntValue();
|
||||
|
||||
return uint64ToDirection(dirNum);
|
||||
}
|
||||
|
||||
GraphNode::GraphNode(ExecutionPlan* plan, size_t id, TRI_vocbase_t* vocbase,
|
||||
AstNode const* direction, AstNode const* graph,
|
||||
std::unique_ptr<BaseOptions> options)
|
||||
|
@ -81,7 +85,7 @@ GraphNode::GraphNode(ExecutionPlan* plan, size_t id, TRI_vocbase_t* vocbase,
|
|||
|
||||
// Direction is already the correct Integer.
|
||||
// Is not inserted by user but by enum.
|
||||
TRI_edge_direction_e baseDirection = parseDirection(direction);
|
||||
_defaultDirection = parseDirection(direction);
|
||||
|
||||
std::unordered_map<std::string, TRI_edge_direction_e> seenCollections;
|
||||
|
||||
|
@ -130,7 +134,7 @@ GraphNode::GraphNode(ExecutionPlan* plan, size_t id, TRI_vocbase_t* vocbase,
|
|||
dir = parseDirection(col->getMember(0));
|
||||
col = col->getMember(1);
|
||||
} else {
|
||||
dir = baseDirection;
|
||||
dir = _defaultDirection;
|
||||
}
|
||||
|
||||
std::string eColName = col->getString();
|
||||
|
@ -219,7 +223,7 @@ GraphNode::GraphNode(ExecutionPlan* plan, size_t id, TRI_vocbase_t* vocbase,
|
|||
if (ServerState::instance()->isRunningInCluster()) {
|
||||
auto c = ci->getCollection(_vocbase->name(), n);
|
||||
if (!c->isSmart()) {
|
||||
addEdgeCollection(n, baseDirection);
|
||||
addEdgeCollection(n, _defaultDirection);
|
||||
} else {
|
||||
std::vector<std::string> names;
|
||||
if (_isSmart) {
|
||||
|
@ -228,11 +232,11 @@ GraphNode::GraphNode(ExecutionPlan* plan, size_t id, TRI_vocbase_t* vocbase,
|
|||
names = c->realNamesForRead();
|
||||
}
|
||||
for (auto const& name : names) {
|
||||
addEdgeCollection(name, baseDirection);
|
||||
addEdgeCollection(name, _defaultDirection);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addEdgeCollection(n, baseDirection);
|
||||
addEdgeCollection(n, _defaultDirection);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,25 +267,17 @@ GraphNode::GraphNode(ExecutionPlan* plan, arangodb::velocypack::Slice const& bas
|
|||
_options(nullptr),
|
||||
_optionsBuilt(false),
|
||||
_isSmart(false) {
|
||||
|
||||
uint64_t dir = arangodb::basics::VelocyPackHelper::stringUInt64(base.get("defaultDirection"));
|
||||
_defaultDirection = uint64ToDirection(dir);
|
||||
|
||||
// Directions
|
||||
VPackSlice dirList = base.get("directions");
|
||||
for (auto const& it : VPackArrayIterator(dirList)) {
|
||||
uint64_t dir = arangodb::basics::VelocyPackHelper::stringUInt64(it);
|
||||
TRI_edge_direction_e d;
|
||||
switch (dir) {
|
||||
case 1:
|
||||
d = TRI_EDGE_IN;
|
||||
break;
|
||||
case 2:
|
||||
d = TRI_EDGE_OUT;
|
||||
break;
|
||||
case 0:
|
||||
TRI_ASSERT(false);
|
||||
default:
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
|
||||
"Invalid direction value");
|
||||
break;
|
||||
}
|
||||
TRI_edge_direction_e d = uint64ToDirection(dir);
|
||||
// Only TRI_EDGE_IN and TRI_EDGE_OUT allowed here
|
||||
TRI_ASSERT(d == TRI_EDGE_IN || d == TRI_EDGE_OUT);
|
||||
_directions.emplace_back(d);
|
||||
}
|
||||
|
||||
|
@ -418,6 +414,9 @@ void GraphNode::toVelocyPackHelper(VPackBuilder& nodes, unsigned flags) const {
|
|||
_graphObj->toVelocyPack(nodes);
|
||||
}
|
||||
|
||||
// Default Direction
|
||||
nodes.add("defaultDirection", VPackValue(_defaultDirection));
|
||||
|
||||
// Directions
|
||||
nodes.add(VPackValue("directions"));
|
||||
{
|
||||
|
|
|
@ -163,6 +163,9 @@ class GraphNode : public ExecutionNode {
|
|||
/// @brief the vertex collection names
|
||||
std::vector<std::unique_ptr<aql::Collection>> _vertexColls;
|
||||
|
||||
/// @brief The default direction given in the query
|
||||
TRI_edge_direction_e _defaultDirection;
|
||||
|
||||
/// @brief The directions edges are followed
|
||||
std::vector<TRI_edge_direction_e> _directions;
|
||||
|
||||
|
|
|
@ -1081,9 +1081,11 @@ function processQuery(query, explain, planIndex) {
|
|||
};
|
||||
|
||||
var label = function (node) {
|
||||
var rc, v, e, edgeCols;
|
||||
var rc, v, e, edgeCols, i, d, directions, isLast;
|
||||
var parts = [];
|
||||
var types = [];
|
||||
// index in this array gives the traversal direction
|
||||
const translate = ['ANY', 'INBOUND', 'OUTBOUND'];
|
||||
switch (node.type) {
|
||||
case 'SingletonNode':
|
||||
return keyword('ROOT');
|
||||
|
@ -1144,10 +1146,9 @@ function processQuery(query, explain, planIndex) {
|
|||
rc += parts.join(', ') + ' ' + keyword('IN') + ' ' +
|
||||
value(node.minMaxDepth) + ' ' + annotation('/* min..maxPathDepth */') + ' ';
|
||||
|
||||
var translate = ['ANY', 'INBOUND', 'OUTBOUND'];
|
||||
var directions = [], d;
|
||||
for (var i = 0; i < node.edgeCollections.length; ++i) {
|
||||
var isLast = (i + 1 === node.edgeCollections.length);
|
||||
directions = [];
|
||||
for (i = 0; i < node.edgeCollections.length; ++i) {
|
||||
isLast = (i + 1 === node.edgeCollections.length);
|
||||
d = node.directions[i];
|
||||
if (!isLast && node.edgeCollections[i] === node.edgeCollections[i + 1]) {
|
||||
// direction ANY is represented by two traversals: an INBOUND and an OUTBOUND traversal
|
||||
|
@ -1259,8 +1260,7 @@ function processQuery(query, explain, planIndex) {
|
|||
if (node.hasOwnProperty('edgeOutVariable')) {
|
||||
parts.push(variableName(node.edgeOutVariable) + ' ' + annotation('/* edge */'));
|
||||
}
|
||||
translate = ['ANY', 'INBOUND', 'OUTBOUND'];
|
||||
let defaultDirection = node.directions[0];
|
||||
let defaultDirection = node.defaultDirection;
|
||||
rc = `${keyword("FOR")} ${parts.join(", ")} ${keyword("IN")} ${keyword(translate[defaultDirection])} ${keyword("SHORTEST_PATH")} `;
|
||||
if (node.hasOwnProperty('startVertexId')) {
|
||||
rc += `'${value(node.startVertexId)}'`;
|
||||
|
@ -1277,13 +1277,25 @@ function processQuery(query, explain, planIndex) {
|
|||
rc += ` ${annotation("/* targetnode */")} `;
|
||||
|
||||
if (Array.isArray(node.graph)) {
|
||||
rc += node.graph.map(function (g, index) {
|
||||
directions = [];
|
||||
for (i = 0; i < node.edgeCollections.length; ++i) {
|
||||
isLast = (i + 1 === node.edgeCollections.length);
|
||||
d = node.directions[i];
|
||||
if (!isLast && node.edgeCollections[i] === node.edgeCollections[i + 1]) {
|
||||
// direction ANY is represented by two traversals: an INBOUND and an OUTBOUND traversal
|
||||
// on the same collection
|
||||
d = 0; // ANY
|
||||
++i;
|
||||
}
|
||||
directions.push({ collection: node.edgeCollections[i], direction: d });
|
||||
}
|
||||
rc += directions.map(function (g, index) {
|
||||
var tmp = '';
|
||||
if (node.directions[index] !== defaultDirection) {
|
||||
tmp += keyword(translate[node.directions[index]]);
|
||||
if (g.direction !== defaultDirection) {
|
||||
tmp += keyword(translate[g.direction]);
|
||||
tmp += ' ';
|
||||
}
|
||||
return tmp + collection(g);
|
||||
return tmp + collection(g.collection);
|
||||
}).join(', ');
|
||||
} else {
|
||||
rc += keyword('GRAPH') + " '" + value(node.graph) + "'";
|
||||
|
@ -1319,8 +1331,7 @@ function processQuery(query, explain, planIndex) {
|
|||
if (node.hasOwnProperty('pathOutVariable')) {
|
||||
parts.push(variableName(node.pathOutVariable) + ' ' + annotation('/* path */'));
|
||||
}
|
||||
translate = ['ANY', 'INBOUND', 'OUTBOUND'];
|
||||
let defaultDirection = node.directions[0];
|
||||
let defaultDirection = node.defaultDirection;
|
||||
rc = `${keyword("FOR")} ${parts.join(", ")} ${keyword("IN")} ${keyword(translate[defaultDirection])} ${keyword("K_SHORTEST_PATHS")} `;
|
||||
if (node.hasOwnProperty('startVertexId')) {
|
||||
rc += `'${value(node.startVertexId)}'`;
|
||||
|
@ -1337,13 +1348,25 @@ function processQuery(query, explain, planIndex) {
|
|||
rc += ` ${annotation("/* targetnode */")} `;
|
||||
|
||||
if (Array.isArray(node.graph)) {
|
||||
rc += node.graph.map(function (g, index) {
|
||||
directions = [];
|
||||
for (i = 0; i < node.edgeCollections.length; ++i) {
|
||||
isLast = (i + 1 === node.edgeCollections.length);
|
||||
d = node.directions[i];
|
||||
if (!isLast && node.edgeCollections[i] === node.edgeCollections[i + 1]) {
|
||||
// direction ANY is represented by two traversals: an INBOUND and an OUTBOUND traversal
|
||||
// on the same collection
|
||||
d = 0; // ANY
|
||||
++i;
|
||||
}
|
||||
directions.push({ collection: node.edgeCollections[i], direction: d });
|
||||
}
|
||||
rc += directions.map(function (g, index) {
|
||||
var tmp = '';
|
||||
if (node.directions[index] !== defaultDirection) {
|
||||
tmp += keyword(translate[node.directions[index]]);
|
||||
if (g.direction !== defaultDirection) {
|
||||
tmp += keyword(translate[g.direction]);
|
||||
tmp += ' ';
|
||||
}
|
||||
return tmp + collection(g);
|
||||
return tmp + collection(g.collection);
|
||||
}).join(', ');
|
||||
} else {
|
||||
rc += keyword('GRAPH') + " '" + value(node.graph) + "'";
|
||||
|
|
Loading…
Reference in New Issue