1
0
Fork 0

Solved conflict

This commit is contained in:
Michael Hackstein 2013-06-13 09:48:46 +02:00
commit fc5f10b3ed
16 changed files with 370 additions and 174 deletions

View File

@ -1,5 +1,18 @@
v1.4
------
----
* changed the HTTP return code from 400 to 404 for some cases when there is a referral
to a non-existing collection or document.
* introduced error code 1909 `too many iterations` that is thrown when graph traversals
hit the `maxIterations` threshold.
* optionally limit traversals to a certain number of iterations
the limitation can be achieved via the traversal API by setting the `maxIterations`
attribute, and also via the AQL `TRAVERSAL` and `TRAVERSAL_TREE` functions by setting
the same attribute. If traversals are not limited by the end user, a server-defined
limit for `maxIterations` may be used to prevent server-side traversals from running
endlessly.
* added graph traversal API at `/_api/traversal`

View File

@ -1277,6 +1277,10 @@ Example calls:
- `minDepth`: Minimum path depths for vertices to be included. This can be used to
include only vertices in the result that are found after a certain minimum depth.
Defaults to 0.
- `maxIterations`: Maximum number of iterations in each traversal. This number can be
set to prevent endless loops in traversal of cyclic graphs. When a traversal performs
as many iterations as the `maxIterations` value, the traversal will abort with an
error. If `maxIterations` is not set, a server-defined value may be used.
- `maxDepth`: Maximum path depth for sub-edges expansion. This can be used to
limit the depth of the traversal to a sensible amount. This should especially be used
for big graphs to limit the traversal to some sensible amount, and for graphs

View File

@ -33,10 +33,10 @@ describe ArangoDB do
body = "{ \"query\" : \"FOR u IN unknowncollection LIMIT 2 RETURN u.n\", \"count\" : true, \"bindVars\" : {}, \"batchSize\" : 2 }"
doc = ArangoDB.log_post("#{prefix}-unknown-collection", cmd, :body => body)
doc.code.should eq(400)
doc.code.should eq(404)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(400)
doc.parsed_response['code'].should eq(404)
doc.parsed_response['errorNum'].should eq(1203)
end

View File

@ -29,10 +29,10 @@ describe ArangoDB do
body = "{ \"query\" : \"FOR u IN unknowncollection LIMIT 2 RETURN u.n\" }"
doc = ArangoDB.log_post("#{prefix}-unknown-collection", cmd, :body => body)
doc.code.should eq(400)
doc.code.should eq(404)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(400)
doc.parsed_response['code'].should eq(404)
doc.parsed_response['errorNum'].should eq(1203)
end

View File

@ -180,10 +180,10 @@ describe ArangoDB do
body = "{ \"collections\" : { \"write\": \"_meow\" }, \"action\" : \"function () { return 1; }\" }"
doc = ArangoDB.log_post("#{prefix}-non-existing-collection", cmd, :body => body)
doc.code.should eq(400)
doc.code.should eq(404)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(400)
doc.parsed_response['code'].should eq(404)
doc.parsed_response['errorNum'].should eq(1203)
end

View File

@ -22,7 +22,7 @@ describe ArangoDB do
cmd = "/_api/document?collection=#{@cv}"
[
"World", "Nothing", "Europe", "Asia", "America", "Australia", "Antarctica", "Africa", "Blackhole",
"World", "Nothing", "Europe", "Asia", "America", "Australia", "Antarctica", "Africa", "Blackhole", "Blackhole2",
"DE", "FR", "GB", "IE", "CN", "JP", "TW", "US", "MX", "AU", "EG", "ZA", "AN",
"London", "Paris", "Lyon", "Cologne","Dusseldorf", "Beijing", "Shanghai", "Tokyo", "Kyoto", "Taipeh", "Perth", "Sydney"
].each do|loc|
@ -44,7 +44,9 @@ describe ArangoDB do
["Asia", "TW"],
["America", "US"],
["America", "MX"],
["Australia", "AU"]
["Australia", "AU"],
["Blackhole", "Blackhole2"],
["Blackhole2", "Blackhole"]
].each do|pair|
from = pair[0]
to = pair[1]
@ -151,7 +153,7 @@ describe ArangoDB do
it "invalid direction" do
body = "{ \"edgeCollection\" : \"#{@ce}\", \"startVertex\" : \"#{@cv}/World\", \"direction\" : \"foo\" }"
doc = ArangoDB.log_post("#{prefix}-visit-invalid-direction", api, :body => body)
doc.code.should eq(400)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
@ -176,6 +178,34 @@ describe ArangoDB do
doc.parsed_response['errorNum'].should eq(500)
end
################################################################################
## traversal abortion
################################################################################
it "traversal abortion, few iterations" do
body = "{ \"edgeCollection\" : \"#{@ce}\", \"startVertex\" : \"#{@cv}/Blackhole\", \"direction\" : \"outbound\", \"uniqueness\" : { \"vertices\" : \"none\", \"edges\" : \"none\" }, \"maxIterations\" : 5 }"
doc = ArangoDB.log_post("#{prefix}-visit-traversal-abort1", api, :body => body)
doc.code.should eq(500)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(500)
doc.parsed_response['errorNum'].should eq(1909)
end
it "traversal abortion, many iterations" do
body = "{ \"edgeCollection\" : \"#{@ce}\", \"startVertex\" : \"#{@cv}/Blackhole\", \"direction\" : \"outbound\", \"uniqueness\" : { \"vertices\" : \"none\", \"edges\" : \"none\" }, \"maxIterations\" : 5000, \"maxDepth\" : 999999, \"visitor\" : \"\" }"
doc = ArangoDB.log_post("#{prefix}-visit-traversal-abort2", api, :body => body)
doc.code.should eq(500)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(500)
doc.parsed_response['errorNum'].should eq(1909)
end
end
################################################################################

View File

@ -144,6 +144,7 @@
"ERROR_GRAPH_INVALID_EDGE" : { "code" : 1906, "message" : "invalid edge" },
"ERROR_GRAPH_COULD_NOT_CREATE_EDGE" : { "code" : 1907, "message" : "could not create edge" },
"ERROR_GRAPH_COULD_NOT_CHANGE_EDGE" : { "code" : 1908, "message" : "could not change edge" },
"ERROR_GRAPH_TOO_MANY_ITERATIONS" : { "code" : 1909, "message" : "too many iterations" },
"ERROR_SESSION_INVALID_SESSION" : { "code" : 1951, "message" : "invalid session" },
"ERROR_SESSION_COULD_NOT_CREATE_SESSION" : { "code" : 1952, "message" : "could not create session" },
"ERROR_SESSION_COULD_NOT_CHANGE_SESSION" : { "code" : 1953, "message" : "could not change session" },

View File

@ -31,6 +31,7 @@ module.define("org/arangodb/graph/traversal", function(exports, module) {
var graph = require("org/arangodb/graph");
var arangodb = require("org/arangodb");
var ArangoError = arangodb.ArangoError;
var db = arangodb.db;
@ -661,6 +662,7 @@ function breadthFirstSearch () {
},
run: function (config, result, startVertex) {
var maxIterations = config.maxIterations, visitCounter = 0;
var toVisit = [ { edge: null, vertex: startVertex, parentIndex: -1 } ];
var visited = { edges: { }, vertices: { } };
@ -674,6 +676,13 @@ function breadthFirstSearch () {
var vertex = current.vertex;
var edge = current.edge;
var path;
if (visitCounter++ > maxIterations) {
var err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_GRAPH_TOO_MANY_ITERATIONS.code;
err.errorMessage = arangodb.errors.ERROR_GRAPH_TOO_MANY_ITERATIONS.message;
throw err;
}
if (current.visit === null || current.visit === undefined) {
current.visit = false;
@ -757,12 +766,20 @@ function depthFirstSearch () {
},
run: function (config, result, startVertex) {
var maxIterations = config.maxIterations, visitCounter = 0;
var toVisit = [ { edge: null, vertex: startVertex, visit: null } ];
var path = { edges: [ ], vertices: [ ] };
var visited = { edges: { }, vertices: { } };
var reverse = checkReverse(config);
while (toVisit.length > 0) {
if (visitCounter++ > maxIterations) {
var err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_GRAPH_TOO_MANY_ITERATIONS.code;
err.errorMessage = arangodb.errors.ERROR_GRAPH_TOO_MANY_ITERATIONS.message;
throw err;
}
// peek at the top of the stack
var current = toVisit[toVisit.length - 1];
var vertex = current.vertex;
@ -871,52 +888,150 @@ ArangoTraverser = function (config) {
visitor: trackingVisitor,
filter: visitAllFilter,
expander: outboundExpander,
datasource: null
datasource: null,
maxIterations: 10000,
minDepth: 0,
maxDepth: 256
}, d;
var err;
if (typeof config !== "object") {
throw "invalid configuration";
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = arangodb.errors.ERROR_BAD_PARAMETER.message;
throw err;
}
// apply defaults
for (d in defaults) {
if (defaults.hasOwnProperty(d)) {
if (! config.hasOwnProperty(d)) {
if (! config.hasOwnProperty(d) || config[d] === undefined) {
config[d] = defaults[d];
}
}
}
if (typeof config.visitor !== "function") {
throw "invalid visitor";
}
if (Array.isArray(config.filter)) {
config.filter.forEach( function (f) {
if (typeof f !== "function") {
throw "invalid filter";
function validate (value, map, param) {
var m;
if (value === null || value === undefined) {
// use first key from map
for (m in map) {
if (map.hasOwnProperty(m)) {
value = m;
break;
}
}
});
}
if (typeof value === 'string') {
value = value.toLowerCase().replace(/-/, "");
if (map[value] !== null) {
return map[value];
}
}
for (m in map) {
if (map.hasOwnProperty(m)) {
if (map[m] === value) {
return value;
}
}
}
var innerFilters = config.filter.slice();
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = "invalid value for " + param;
throw err;
}
config.uniqueness = {
vertices: validate(config.uniqueness && config.uniqueness.vertices, {
global: ArangoTraverser.UNIQUE_GLOBAL,
none: ArangoTraverser.UNIQUE_NONE,
path: ArangoTraverser.UNIQUE_PATH
}, "uniqueness.vertices"),
edges: validate(config.uniqueness && config.uniqueness.edges, {
global: ArangoTraverser.UNIQUE_GLOBAL,
none: ArangoTraverser.UNIQUE_NONE,
path: ArangoTraverser.UNIQUE_PATH
}, "uniqueness.edges")
};
config.strategy = validate(config.strategy, {
depthfirst: ArangoTraverser.DEPTH_FIRST,
breadthfirst: ArangoTraverser.BREADTH_FIRST
}, "strategy");
var combinedFilter = function (config, vertex, path) {
return combineFilters(innerFilters, config, vertex, path);
};
config.order = validate(config.order, {
preorder: ArangoTraverser.PRE_ORDER,
postorder: ArangoTraverser.POST_ORDER
}, "order");
config.filter = combinedFilter;
config.itemOrder = validate(config.itemOrder, {
forward: ArangoTraverser.FORWARD,
backward: ArangoTraverser.BACKWARD
}, "itemOrder");
if (typeof config.visitor !== "function") {
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = "invalid visitor function";
throw err;
}
if (typeof config.filter !== "function") {
throw "invalid filter";
// prepare an array of filters
var filters = [ ];
if (config.minDepth !== undefined && config.minDepth >= 0) {
filters.push(minDepthFilter);
}
if (config.maxDepth !== undefined && config.maxDepth > 0) {
filters.push(maxDepthFilter);
}
if (! Array.isArray(config.filter)) {
config.filter = [ config.filter ];
}
config.filter.forEach( function (f) {
if (typeof f !== "function") {
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = "invalid filter function";
throw err;
}
filters.push(f);
});
if (filters.length === 0) {
filters.push(visitAllFilter);
}
config.filter = function (config, vertex, path) {
return combineFilters(filters, config, vertex, path);
};
if (typeof config.expander !== "function") {
config.expander = validate(config.expander, {
outbound: outboundExpander,
inbound: inboundExpander,
any: anyExpander
}, "expander");
}
if (typeof config.expander !== "function") {
throw "invalid expander";
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = "invalid expander function";
throw err;
}
if (typeof config.datasource !== "object") {
throw "invalid datasource";
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = "invalid datasource";
throw err;
}
this.config = config;

View File

@ -65,32 +65,6 @@ function notFound (req, res, code, message) {
message);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief validate and translate the argument given in value
////////////////////////////////////////////////////////////////////////////////
function validateArg (value, map) {
if (value === null || value === undefined) {
var m;
// use first key from map
for (m in map) {
if (map.hasOwnProperty(m)) {
value = m;
break;
}
}
}
if (typeof value === 'string') {
value = value.toLowerCase().replace(/-/, "");
if (map[value] !== null) {
return map[value];
}
}
return undefined;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief execute a server-side traversal
///
@ -683,7 +657,8 @@ function post_api_traversal(req, res) {
catch (err2) {
}
if (edgeCollection === undefined || edgeCollection == null) {
if (edgeCollection === undefined ||
edgeCollection === null) {
return notFound(req, res, arangodb.ERROR_ARANGO_COLLECTION_NOT_FOUND, "invalid edgeCollection");
}
@ -734,11 +709,7 @@ function post_api_traversal(req, res) {
var expander;
if (json.direction !== undefined) {
expander = validateArg(json.direction, {
'outbound': traversal.outboundExpander,
'inbound': traversal.inboundExpander,
'any': traversal.anyExpander
});
expander = json.direction;
}
else if (json.expander !== undefined) {
try {
@ -761,35 +732,16 @@ function post_api_traversal(req, res) {
params: json,
edgeCollection: edgeCollection,
datasource: traversal.collectionDatasourceFactory(edgeCollection),
strategy: validateArg(json.strategy, {
'depthfirst': Traverser.DEPTH_FIRST,
'breadthfirst': Traverser.BREADTH_FIRST
}),
order: validateArg(json.order, {
'preorder': Traverser.PRE_ORDER,
'postorder': Traverser.POST_ORDER
}),
itemOrder: validateArg(json.itemOrder, {
'forward': Traverser.FORWARD,
'backward': Traverser.BACKWARD
}),
strategy: json.strategy,
order: json.order,
itemOrder: json.itemOrder,
expander: expander,
visitor: visitor,
filter: filters,
minDepth: json.minDepth || 0,
minDepth: json.minDepth,
maxDepth: json.maxDepth,
uniqueness: {
vertices: validateArg(json.uniqueness && json.uniqueness.vertices, {
'global': Traverser.UNIQUE_GLOBAL,
'none': Traverser.UNIQUE_NONE,
'path': Traverser.UNIQUE_PATH
}),
edges: validateArg(json.uniqueness && json.uniqueness.edges, {
'global': Traverser.UNIQUE_GLOBAL,
'none': Traverser.UNIQUE_NONE,
'path': Traverser.UNIQUE_PATH
})
}
maxIterations: json.maxIterations,
uniqueness: json.uniqueness
};
// assemble result object
@ -815,12 +767,17 @@ function post_api_traversal(req, res) {
// run the traversal
// -----------------------------------------
var traverser = new Traverser(config);
var traverser;
try {
traverser = new Traverser(config);
traverser.traverse(result, doc);
actions.resultOk(req, res, actions.HTTP_OK, { result : result });
}
catch (err7) {
if (traverser === undefined) {
// error during traversal setup
return badParam(req, res, err7);
}
actions.resultException(req, res, err7, undefined, false);
}
}

View File

@ -144,6 +144,7 @@
"ERROR_GRAPH_INVALID_EDGE" : { "code" : 1906, "message" : "invalid edge" },
"ERROR_GRAPH_COULD_NOT_CREATE_EDGE" : { "code" : 1907, "message" : "could not create edge" },
"ERROR_GRAPH_COULD_NOT_CHANGE_EDGE" : { "code" : 1908, "message" : "could not change edge" },
"ERROR_GRAPH_TOO_MANY_ITERATIONS" : { "code" : 1909, "message" : "too many iterations" },
"ERROR_SESSION_INVALID_SESSION" : { "code" : 1951, "message" : "invalid session" },
"ERROR_SESSION_COULD_NOT_CREATE_SESSION" : { "code" : 1952, "message" : "could not create session" },
"ERROR_SESSION_COULD_NOT_CHANGE_SESSION" : { "code" : 1953, "message" : "could not change session" },

View File

@ -30,6 +30,7 @@
var graph = require("org/arangodb/graph");
var arangodb = require("org/arangodb");
var ArangoError = arangodb.ArangoError;
var db = arangodb.db;
@ -660,6 +661,7 @@ function breadthFirstSearch () {
},
run: function (config, result, startVertex) {
var maxIterations = config.maxIterations, visitCounter = 0;
var toVisit = [ { edge: null, vertex: startVertex, parentIndex: -1 } ];
var visited = { edges: { }, vertices: { } };
@ -673,6 +675,13 @@ function breadthFirstSearch () {
var vertex = current.vertex;
var edge = current.edge;
var path;
if (visitCounter++ > maxIterations) {
var err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_GRAPH_TOO_MANY_ITERATIONS.code;
err.errorMessage = arangodb.errors.ERROR_GRAPH_TOO_MANY_ITERATIONS.message;
throw err;
}
if (current.visit === null || current.visit === undefined) {
current.visit = false;
@ -756,12 +765,20 @@ function depthFirstSearch () {
},
run: function (config, result, startVertex) {
var maxIterations = config.maxIterations, visitCounter = 0;
var toVisit = [ { edge: null, vertex: startVertex, visit: null } ];
var path = { edges: [ ], vertices: [ ] };
var visited = { edges: { }, vertices: { } };
var reverse = checkReverse(config);
while (toVisit.length > 0) {
if (visitCounter++ > maxIterations) {
var err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_GRAPH_TOO_MANY_ITERATIONS.code;
err.errorMessage = arangodb.errors.ERROR_GRAPH_TOO_MANY_ITERATIONS.message;
throw err;
}
// peek at the top of the stack
var current = toVisit[toVisit.length - 1];
var vertex = current.vertex;
@ -870,52 +887,150 @@ ArangoTraverser = function (config) {
visitor: trackingVisitor,
filter: visitAllFilter,
expander: outboundExpander,
datasource: null
datasource: null,
maxIterations: 10000,
minDepth: 0,
maxDepth: 256
}, d;
var err;
if (typeof config !== "object") {
throw "invalid configuration";
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = arangodb.errors.ERROR_BAD_PARAMETER.message;
throw err;
}
// apply defaults
for (d in defaults) {
if (defaults.hasOwnProperty(d)) {
if (! config.hasOwnProperty(d)) {
if (! config.hasOwnProperty(d) || config[d] === undefined) {
config[d] = defaults[d];
}
}
}
if (typeof config.visitor !== "function") {
throw "invalid visitor";
}
if (Array.isArray(config.filter)) {
config.filter.forEach( function (f) {
if (typeof f !== "function") {
throw "invalid filter";
function validate (value, map, param) {
var m;
if (value === null || value === undefined) {
// use first key from map
for (m in map) {
if (map.hasOwnProperty(m)) {
value = m;
break;
}
}
});
}
if (typeof value === 'string') {
value = value.toLowerCase().replace(/-/, "");
if (map[value] !== null) {
return map[value];
}
}
for (m in map) {
if (map.hasOwnProperty(m)) {
if (map[m] === value) {
return value;
}
}
}
var innerFilters = config.filter.slice();
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = "invalid value for " + param;
throw err;
}
config.uniqueness = {
vertices: validate(config.uniqueness && config.uniqueness.vertices, {
global: ArangoTraverser.UNIQUE_GLOBAL,
none: ArangoTraverser.UNIQUE_NONE,
path: ArangoTraverser.UNIQUE_PATH
}, "uniqueness.vertices"),
edges: validate(config.uniqueness && config.uniqueness.edges, {
global: ArangoTraverser.UNIQUE_GLOBAL,
none: ArangoTraverser.UNIQUE_NONE,
path: ArangoTraverser.UNIQUE_PATH
}, "uniqueness.edges")
};
config.strategy = validate(config.strategy, {
depthfirst: ArangoTraverser.DEPTH_FIRST,
breadthfirst: ArangoTraverser.BREADTH_FIRST
}, "strategy");
var combinedFilter = function (config, vertex, path) {
return combineFilters(innerFilters, config, vertex, path);
};
config.order = validate(config.order, {
preorder: ArangoTraverser.PRE_ORDER,
postorder: ArangoTraverser.POST_ORDER
}, "order");
config.filter = combinedFilter;
config.itemOrder = validate(config.itemOrder, {
forward: ArangoTraverser.FORWARD,
backward: ArangoTraverser.BACKWARD
}, "itemOrder");
if (typeof config.visitor !== "function") {
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = "invalid visitor function";
throw err;
}
if (typeof config.filter !== "function") {
throw "invalid filter";
// prepare an array of filters
var filters = [ ];
if (config.minDepth !== undefined && config.minDepth >= 0) {
filters.push(minDepthFilter);
}
if (config.maxDepth !== undefined && config.maxDepth > 0) {
filters.push(maxDepthFilter);
}
if (! Array.isArray(config.filter)) {
config.filter = [ config.filter ];
}
config.filter.forEach( function (f) {
if (typeof f !== "function") {
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = "invalid filter function";
throw err;
}
filters.push(f);
});
if (filters.length === 0) {
filters.push(visitAllFilter);
}
config.filter = function (config, vertex, path) {
return combineFilters(filters, config, vertex, path);
};
if (typeof config.expander !== "function") {
config.expander = validate(config.expander, {
outbound: outboundExpander,
inbound: inboundExpander,
any: anyExpander
}, "expander");
}
if (typeof config.expander !== "function") {
throw "invalid expander";
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = "invalid expander function";
throw err;
}
if (typeof config.datasource !== "object") {
throw "invalid datasource";
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_BAD_PARAMETER.code;
err.errorMessage = "invalid datasource";
throw err;
}
this.config = config;

View File

@ -1853,8 +1853,14 @@ function resultException (req, res, err, headers, verbose) {
switch (num) {
case arangodb.ERROR_INTERNAL:
case arangodb.ERROR_OUT_OF_MEMORY:
case arangodb.ERROR_GRAPH_TOO_MANY_ITERATIONS:
code = exports.HTTP_SERVER_ERROR;
break;
case arangodb.ERROR_ARANGO_COLLECTION_NOT_FOUND:
case arangodb.ERROR_ARANGO_DOCUMENT_NOT_FOUND:
code = exports.HTTP_NOT_FOUND;
break;
case arangodb.ERROR_ARANGO_DUPLICATE_NAME:
case arangodb.ERROR_ARANGO_DUPLICATE_IDENTIFIER:

View File

@ -3478,27 +3478,6 @@ function TRAVERSAL_FUNC (func, vertexCollection, edgeCollection, startVertex, di
});
}
function validate (value, map) {
if (value === null || value === undefined) {
var m;
// use first key from map
for (m in map) {
if (map.hasOwnProperty(m)) {
value = m;
break;
}
}
}
if (typeof value === 'string') {
value = value.toLowerCase().replace(/-/, "");
if (map[value] !== null) {
return map[value];
}
}
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, func);
}
if (typeof params.visitor !== "function") {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, func);
}
@ -3508,55 +3487,16 @@ function TRAVERSAL_FUNC (func, vertexCollection, edgeCollection, startVertex, di
params.maxDepth = 256;
}
// prepare an array of filters
var filters = [ ];
if (params.minDepth !== undefined) {
filters.push(TRAVERSAL.minDepthFilter);
}
if (params.maxDepth !== undefined) {
filters.push(TRAVERSAL.maxDepthFilter);
}
if (filters.length === 0) {
filters.push(TRAVERSAL.visitAllFilter);
}
var config = {
connect: params.connect,
datasource: TRAVERSAL.collectionDatasourceFactory(edgeCollection),
strategy: validate(params.strategy, {
'depthfirst': TRAVERSAL.Traverser.DEPTH_FIRST,
'breadthfirst': TRAVERSAL.Traverser.BREADTH_FIRST
}),
order: validate(params.order, {
'preorder': TRAVERSAL.Traverser.PRE_ORDER,
'postorder': TRAVERSAL.Traverser.POST_ORDER
}),
itemOrder: validate(params.itemOrder, {
'forward': TRAVERSAL.Traverser.FORWARD,
'backward': TRAVERSAL.Traverser.BACKWARD
}),
trackPaths: params.paths || false,
visitor: params.visitor,
maxDepth: params.maxDepth,
minDepth: params.minDepth,
filter: filters,
uniqueness: {
vertices: validate(params.uniqueness && params.uniqueness.vertices, {
'global': TRAVERSAL.Traverser.UNIQUE_GLOBAL,
'none': TRAVERSAL.Traverser.UNIQUE_NONE,
'path': TRAVERSAL.Traverser.UNIQUE_PATH
}),
edges: validate(params.uniqueness && params.uniqueness.edges, {
'global': TRAVERSAL.Traverser.UNIQUE_GLOBAL,
'none': TRAVERSAL.Traverser.UNIQUE_NONE,
'path': TRAVERSAL.Traverser.UNIQUE_PATH
})
},
expander: validate(direction, {
'outbound': TRAVERSAL.outboundExpander,
'inbound': TRAVERSAL.inboundExpander,
'any': TRAVERSAL.anyExpander
})
maxIterations: params.maxIterations,
uniqueness: params.uniqueness,
expander: direction
};
if (params.followEdges) {

View File

@ -198,7 +198,7 @@ ERROR_KEYVALUE_KEY_NOT_REMOVED,1805,"key value not removed","Will be raised when
ERROR_KEYVALUE_NO_VALUE,1806,"missing value","Will be raised when the value is missing"
################################################################################
## Graph errors
## Graph / traversal errors
################################################################################
ERROR_GRAPH_INVALID_GRAPH,1901,"invalid graph","Will be raised when an invalid name is passed to the server"
@ -209,6 +209,7 @@ ERROR_GRAPH_COULD_NOT_CHANGE_VERTEX,1905,"could not change vertex","Will be rais
ERROR_GRAPH_INVALID_EDGE,1906,"invalid edge","Will be raised when an invalid edge id is passed to the server"
ERROR_GRAPH_COULD_NOT_CREATE_EDGE,1907,"could not create edge","Will be raised when the edge could not be created"
ERROR_GRAPH_COULD_NOT_CHANGE_EDGE,1908,"could not change edge","Will be raised when the edge could not be changed"
ERROR_GRAPH_TOO_MANY_ITERATIONS,1909,"too many iterations","Will be raised when too many iterations are done in a graph traversal"
################################################################################
## Session errors

View File

@ -140,6 +140,7 @@ void TRI_InitialiseErrorMessages (void) {
REG_ERROR(ERROR_GRAPH_INVALID_EDGE, "invalid edge");
REG_ERROR(ERROR_GRAPH_COULD_NOT_CREATE_EDGE, "could not create edge");
REG_ERROR(ERROR_GRAPH_COULD_NOT_CHANGE_EDGE, "could not change edge");
REG_ERROR(ERROR_GRAPH_TOO_MANY_ITERATIONS, "too many iterations");
REG_ERROR(ERROR_SESSION_INVALID_SESSION, "invalid session");
REG_ERROR(ERROR_SESSION_COULD_NOT_CREATE_SESSION, "could not create session");
REG_ERROR(ERROR_SESSION_COULD_NOT_CHANGE_SESSION, "could not change session");

View File

@ -306,6 +306,8 @@ extern "C" {
/// Will be raised when the edge could not be created
/// - 1908: @LIT{could not change edge}
/// Will be raised when the edge could not be changed
/// - 1909: @LIT{too many iterations}
/// Will be raised when too many iterations are done in a graph traversal
/// - 1951: @LIT{invalid session}
/// Will be raised when an invalid session id is passed to the server
/// - 1952: @LIT{could not create session}
@ -1751,6 +1753,16 @@ void TRI_InitialiseErrorMessages (void);
#define TRI_ERROR_GRAPH_COULD_NOT_CHANGE_EDGE (1908)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1909: ERROR_GRAPH_TOO_MANY_ITERATIONS
///
/// too many iterations
///
/// Will be raised when too many iterations are done in a graph traversal
////////////////////////////////////////////////////////////////////////////////
#define TRI_ERROR_GRAPH_TOO_MANY_ITERATIONS (1909)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1951: ERROR_SESSION_INVALID_SESSION
///