1
0
Fork 0

Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel

This commit is contained in:
Michael Hackstein 2014-05-20 14:43:47 +02:00
commit f8d2faf8d5
2 changed files with 272 additions and 67 deletions

View File

@ -3971,6 +3971,34 @@ function DATE_MILLISECOND (value) {
// --SECTION-- graph functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief find all paths through a graph, INTERNAL part called recursively
////////////////////////////////////////////////////////////////////////////////
function GET_SUB_EDGES (edgeCollections, direction, vertexId) {
if (!Array.isArray(edgeCollections)) {
edgeCollections = [edgeCollections];
}
var result = [];
edgeCollections.forEach(function (edgeCollection) {
if (direction === 1) {
result = result.concat(edgeCollection.outEdges(vertexId));
}
else if (direction === 2) {
result = result.concat(edgeCollection.inEdges(vertexId));
}
else if (direction === 3) {
result = result.concat(edgeCollection.edges(vertexId));
}
});
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief find all paths through a graph, INTERNAL part called recursively
////////////////////////////////////////////////////////////////////////////////
@ -3993,18 +4021,9 @@ function GRAPH_SUBNODES (searchAttributes, vertexId, visited, edges, vertices, l
return result;
}
var subEdges;
if (searchAttributes.direction === 1) {
subEdges = searchAttributes.edgeCollection.outEdges(vertexId);
}
else if (searchAttributes.direction === 2) {
subEdges = searchAttributes.edgeCollection.inEdges(vertexId);
}
else if (searchAttributes.direction === 3) {
subEdges = searchAttributes.edgeCollection.edges(vertexId);
}
var subEdges = GET_SUB_EDGES(
searchAttributes.edgeCollection, searchAttributes.direction, vertexId
);
var i, j, k;
for (i = 0; i < subEdges.length; ++i) {
@ -4125,73 +4144,92 @@ function GRAPH_PATHS (vertices, edgeCollection, direction, followCycles, minLeng
function GENERAL_GRAPH_PATHS (graphname, direction, followCycles, minLength, maxLength) {
"use strict";
/*var searchDirection;
var searchDirection;
direction = direction || "outbound";
followCycles = followCycles || false;
minLength = minLength || 0;
maxLength = maxLength !== undefined ? maxLength : 10;
var graph = DOCUMENT_HANDLE("_graph" + graphname);
// check graph exists and load edgeDefintions
var graph = DOCUMENT_HANDLE("_graphs/" + graphname);
if (!graph) {
THROW(INTERNAL.errors.ERROR_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "GRAPH_PATHS");
THROW(INTERNAL.errors.ERROR_GRAPH_INVALID_GRAPH, "GRAPH_EDGES");
}
var vertexCollections = [];
var startCollections = [], edgeCollections = [];
// validate arguments
if (direction === "outbound") {
searchDirection = 1;
graph.__edgeDefinitions.forEach(function (def) {
vertexCollections.concat(def.from);
});
}
else if (direction === "inbound") {
graph.__edgeDefinitions.forEach(function (def) {
vertexCollections.concat(def.to);
});
searchDirection = 2;
}
else if (direction === "any") {
graph.__edgeDefinitions.forEach(function (def) {
vertexCollections.concat(def.to);
vertexCollections.concat(def.from);
});
searchDirection = 3;
}
else {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "GRAPH_PATHS");
}
// validate direction and create edgeCollection array.
graph.edgeDefinitions.forEach(function (def) {
if (direction === "outbound") {
searchDirection = 1;
def.from.forEach(function (s) {
if (startCollections.indexOf(s) === -1) {
startCollections.push(s);
}
});
}
else if (direction === "inbound") {
searchDirection = 2;
def.to.forEach(function (s) {
if (startCollections.indexOf(s) === -1) {
startCollections.push(s);
}
});
}
else if (direction === "any") {
def.from.forEach(function (s) {
searchDirection = 3;
if (startCollections.indexOf(s) === -1) {
startCollections.push(s);
}
});
def.to.forEach(function (s) {
if (startCollections.indexOf(s) === -1) {
startCollections.push(s);
}
});
}
else {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "GRAPH_PATHS");
}
if (edgeCollections.indexOf(def.collection) === -1) {
edgeCollections.push(COLLECTION(def.collection));
}
});
if (minLength < 0 || maxLength < 0 || minLength > maxLength) {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "GRAPH_PATHS");
}
var searchAttributes = {
//edgeCollection : COLLECTION(edgeCollection),
minLength : minLength,
maxLength : maxLength,
direction : searchDirection,
followCycles : followCycles
};
var result = [ ];
var n = vertices.length, i, j;
for (i = 0; i < n; ++i) {
var vertex = vertices[i];
var visited = { };
startCollections.forEach(function (startCollection) {
visited[vertex._id] = true;
//GRAPH_SUBNODES (searchAttributes, vertexId, visited, edges, vertices, level) {
var connected = GRAPH_SUBNODES(searchAttributes, vertex._id, visited, [ ], [ vertex ], 0);
for (j = 0; j < connected.length; ++j) {
result.push(connected[j]);
var searchAttributes = {
edgeCollection : edgeCollections,
minLength : minLength,
maxLength : maxLength,
direction : searchDirection,
followCycles : followCycles
};
var vertices = GET_DOCUMENTS(startCollection);
var n = vertices.length, i, j;
for (i = 0; i < n; ++i) {
var vertex = vertices[i];
var visited = { };
visited[vertex._id] = true;
var connected = GRAPH_SUBNODES(searchAttributes, vertex._id, visited, [ ], [ vertex ], 0);
for (j = 0; j < connected.length; ++j) {
result.push(connected[j]);
}
}
}
return result;*/
});
return result;
}
@ -4800,6 +4838,7 @@ exports.GRAPH_TRAVERSAL = GRAPH_TRAVERSAL;
exports.GRAPH_TRAVERSAL_TREE = GRAPH_TRAVERSAL_TREE;
exports.GRAPH_EDGES = GRAPH_EDGES;
exports.GENERAL_GRAPH_EDGES = GENERAL_GRAPH_EDGES;
exports.GENERAL_GRAPH_PATHS = GENERAL_GRAPH_PATHS;
exports.GRAPH_NEIGHBORS = GRAPH_NEIGHBORS;
exports.NOT_NULL = NOT_NULL;
exports.FIRST_LIST = FIRST_LIST;

View File

@ -116,13 +116,6 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
/// @brief checks EDGES()
////////////////////////////////////////////////////////////////////////////////
//graphname,
//startvertex,
//direction,
//edgeexamples,
//collectionRestrictions
testEdgesAny: function () {
var actual;
@ -188,11 +181,184 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite for GRAPH_PATHS() function
////////////////////////////////////////////////////////////////////////////////
function ahuacatlQueryGeneralPathsTestSuite() {
var vertex = null;
var edge = null;
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp: function () {
db._drop("UnitTestsAhuacatlVertex1");
db._drop("UnitTestsAhuacatlVertex2");
db._drop("UnitTestsAhuacatlVertex3");
db._drop("UnitTestsAhuacatlVertex4");
db._drop("UnitTestsAhuacatlEdge1");
db._drop("UnitTestsAhuacatlEdge2");
e1 = "UnitTestsAhuacatlEdge1";
e2 = "UnitTestsAhuacatlEdge2";
vertex1 = db._create("UnitTestsAhuacatlVertex1");
vertex2 = db._create("UnitTestsAhuacatlVertex2");
vertex3 = db._create("UnitTestsAhuacatlVertex3");
vertex4 = db._create("UnitTestsAhuacatlVertex4");
edge1 = db._createEdgeCollection(e1);
edge2 = db._createEdgeCollection(e2);
var v1 = vertex1.save({ _key: "v1" });
var v2 = vertex1.save({ _key: "v2" });
var v3 = vertex2.save({ _key: "v3" });
var v4 = vertex2.save({ _key: "v4" });
var v5 = vertex3.save({ _key: "v5" });
var v6 = vertex3.save({ _key: "v6" });
var v7 = vertex4.save({ _key: "v7" });
try {
db._collection("_graphs").remove("_graphs/bla3")
} catch (err) {
}
var g = graph._create(
"bla3",
graph.edgeDefinitions(
graph._undirectedRelationDefinition("UnitTestsAhuacatlEdge1", "UnitTestsAhuacatlVertex1"),
graph._directedRelationDefinition("UnitTestsAhuacatlEdge2",
["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"],
["UnitTestsAhuacatlVertex3", "UnitTestsAhuacatlVertex4"]
)
)
);
function makeEdge(from, to, collection) {
collection.save(from, to, { what: from.split("/")[1] + "->" + to.split("/")[1] });
}
makeEdge(v1._id, v2._id, g[e1]);
makeEdge(v2._id, v1._id, g[e1]);
makeEdge(v1._id, v5._id, g[e2]);
makeEdge(v2._id, v5._id, g[e2]);
makeEdge(v4._id, v7._id, g[e2]);
makeEdge(v3._id, v5._id, g[e2]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown: function () {
db._drop("UnitTestsAhuacatlVertex1");
db._drop("UnitTestsAhuacatlVertex2");
db._drop("UnitTestsAhuacatlVertex3");
db._drop("UnitTestsAhuacatlVertex4");
db._drop("UnitTestsAhuacatlEdge1");
db._drop("UnitTestsAhuacatlEdge2");
db._collection("_graphs").remove("_graphs/bla3");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief checks EDGES()
////////////////////////////////////////////////////////////////////////////////
testPaths: function () {
var actual, result= {}, i = 0, ed;
actual = getQueryResults("FOR e IN GRAPH_PATHS('bla3') SORT e.source._key,e.destination._key RETURN [e.source._key,e.destination._key,e.edges]");
actual.forEach(function (p) {
i++;
ed = "";
p[2].forEach(function (e) {
ed += "|" + e._from.split("/")[1] + "->" + e._to.split("/")[1];
});
result[i + ":" + p[0] + p[1]] = ed;
});
assertEqual(result["1:v1v1"] , "");
assertEqual(result["2:v1v2"] , "|v1->v2");
assertEqual(result["3:v1v5"] , "|v1->v2|v2->v5");
assertEqual(result["4:v1v5"] , "|v1->v5");
assertEqual(result["5:v2v1"] , "|v2->v1");
assertEqual(result["6:v2v2"] , "");
assertEqual(result["7:v2v5"] , "|v2->v5");
assertEqual(result["8:v2v5"] , "|v2->v1|v1->v5");
assertEqual(result["9:v3v3"] , "");
assertEqual(result["10:v3v5"] , "|v3->v5");
assertEqual(result["11:v4v4"] , "");
assertEqual(result["12:v4v7"] , "|v4->v7");
},
testPathsWithDirectionAnyAndMaxLength1: function () {
var actual, result= {}, i = 0, ed;
actual = getQueryResults("FOR e IN GRAPH_PATHS('bla3', 'any', false , 1 , 1) SORT e.source._key,e.destination._key RETURN [e.source._key,e.destination._key,e.edges]");
actual.forEach(function (p) {
i++;
ed = "";
p[2].forEach(function (e) {
ed += "|" + e._from.split("/")[1] + "->" + e._to.split("/")[1];
});
result[i + ":" + p[0] + p[1]] = ed;
});
assertEqual(result["1:v1v2"] , "|v2->v1");
assertEqual(result["2:v1v2"] , "|v1->v2");
assertEqual(result["3:v1v5"] , "|v1->v5");
assertEqual(result["4:v2v1"] , "|v1->v2");
assertEqual(result["5:v2v1"] , "|v2->v1");
assertEqual(result["6:v2v5"] , "|v2->v5");
assertEqual(result["7:v3v5"] , "|v3->v5");
assertEqual(result["8:v4v7"] , "|v4->v7");
assertEqual(result["9:v5v1"] , "|v1->v5");
assertEqual(result["10:v5v2"] , "|v2->v5");
assertEqual(result["11:v5v3"] , "|v3->v5");
assertEqual(result["12:v7v4"] , "|v4->v7");
},
testInBoundPaths: function () {
var actual, result= {}, i = 0, ed;
actual = getQueryResults("FOR e IN GRAPH_PATHS('bla3', 'inbound', false, 1) SORT e.source._key,e.destination._key RETURN [e.source._key,e.destination._key,e.edges]");
actual.forEach(function (p) {
i++;
ed = "";
p[2].forEach(function (e) {
ed += "|" + e._from.split("/")[1] + "->" + e._to.split("/")[1];
});
result[i + ":" + p[0] + p[1]] = ed;
});
assertEqual(result["1:v1v2"] , "|v2->v1");
assertEqual(result["2:v2v1"] , "|v1->v2");
assertEqual(result["3:v5v1"] , "|v1->v5");
assertEqual(result["4:v5v1"] , "|v2->v5|v1->v2");
assertEqual(result["5:v5v2"] , "|v1->v5|v2->v1");
assertEqual(result["6:v5v2"] , "|v2->v5");
assertEqual(result["7:v5v3"] , "|v3->v5");
assertEqual(result["8:v7v4"] , "|v4->v7");
}
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(ahuacatlQueryGeneralEdgesTestSuite);
jsunity.run(ahuacatlQueryGeneralPathsTestSuite);
return jsunity.done();