1
0
Fork 0

fixes for traversal and multi-modify

This commit is contained in:
Jan Steemann 2015-12-08 14:50:05 +01:00
parent 0a678263fb
commit ee6792dd6b
6 changed files with 85 additions and 9 deletions

View File

@ -123,7 +123,8 @@ Ast::Ast (Query* query)
_root(nullptr),
_queries(),
_writeCollections(),
_functionsMayAccessDocuments(false) {
_functionsMayAccessDocuments(false),
_containsTraversal(false) {
TRI_ASSERT(_query != nullptr);
@ -1230,6 +1231,8 @@ AstNode* Ast::createNodeTraversal (char const* vertexVarName,
TRI_ASSERT(node->numMembers() == 4);
_containsTraversal = true;
return node;
}
@ -1254,6 +1257,8 @@ AstNode* Ast::createNodeTraversal (char const* vertexVarName,
TRI_ASSERT(node->numMembers() == 5);
_containsTraversal = true;
return node;
}
@ -1281,6 +1286,8 @@ AstNode* Ast::createNodeTraversal (char const* vertexVarName,
TRI_ASSERT(node->numMembers() == 6);
_containsTraversal = true;
return node;
}

View File

@ -202,6 +202,14 @@ namespace triagens {
return _functionsMayAccessDocuments;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the query contains a traversal
////////////////////////////////////////////////////////////////////////////////
bool containsTraversal () const {
return _containsTraversal;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief convert the AST into JSON
/// the caller is responsible for freeing the JSON later
@ -998,6 +1006,12 @@ namespace triagens {
bool _functionsMayAccessDocuments;
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the query contains a traversal
////////////////////////////////////////////////////////////////////////////////
bool _containsTraversal;
////////////////////////////////////////////////////////////////////////////////
/// @brief a singleton no-op node instance
////////////////////////////////////////////////////////////////////////////////

View File

@ -471,6 +471,11 @@ ModificationOptions ExecutionPlan::createModificationOptions (AstNode const* nod
// no functions in the query can access document data...
bool isReadWrite = false;
if (_ast->containsTraversal()) {
// its unclear which collections the traversal will access
isReadWrite = true;
}
else {
auto const collections = _ast->query()->collections();
for (auto const& it : *(collections->collections())) {
@ -479,6 +484,7 @@ ModificationOptions ExecutionPlan::createModificationOptions (AstNode const* nod
break;
}
}
}
if (! isReadWrite) {
// no collection is used in both read and write mode

View File

@ -3687,6 +3687,12 @@ int triagens::aql::patchUpdateStatementsRule (Optimizer* opt,
}
}
if (type == EN::TRAVERSAL) {
// unclear what will be read by the traversal
modified = false;
break;
}
dep = dep->getFirstDependency();
}

View File

@ -683,10 +683,16 @@ function processQuery (query, explain) {
}
rc += " " +
keyword("IN") + " " +
node.minMaxDepth + " " + annotation("/* min..maxPathDepth */") + " " +
value(node.minMaxDepth) + " " + annotation("/* min..maxPathDepth */") + " " +
keyword("OUTBOUND") +
" '" + node.vertexId + "' " + annotation("/* Startnode */") + " " +
keyword("GRAPH") + " '" + node.graph + "'";
" '" + value(node.vertexId) + "' " + annotation("/* startnode */") + " ";
if (Array.isArray(node.graph)) {
rc += node.graph.map(function(g) { return collection(g); }).join(", ");
}
else {
rc += keyword("GRAPH") + " '" + value(node.graph) + "'";
}
traversalDetails.push(node);
if (node.hasOwnProperty('simpleExpressions')) {

View File

@ -73,6 +73,43 @@ function ahuacatlMultiModifySuite () {
c3 = null;
},
testTraversalAndModification : function () {
c1.insert({ _key: "1" });
c1.insert({ _key: "2" });
c1.insert({ _key: "3" });
c1.insert({ _key: "4" });
c3.insert(cn1 + "/1", cn1 + "/2", { });
c3.insert(cn1 + "/2", cn1 + "/3", { });
var q = "FOR v IN 1..99 OUTBOUND '" + cn1 + "/1' @@e REMOVE v._key IN @@cn";
var actual = AQL_EXECUTE(q, { "@cn": cn1, "@e": cn3 });
assertEqual([ ], actual.json);
assertEqual(2, actual.stats.writesExecuted);
assertEqual(2, c1.count());
assertTrue(c1.exists("1"));
assertTrue(c1.exists("4"));
assertEqual(2, c3.count());
},
testTraversalAndModificationBig : function () {
var i;
for (i = 1; i <= 2010; ++i) {
c1.insert({ _key: String(i) });
if (i !== 2010) {
c3.insert(cn1 + "/" + String(i), cn1 + "/" + String(i + 1), { });
}
}
var q = "FOR v IN 1..2010 OUTBOUND '" + cn1 + "/1' @@e REMOVE v._key IN @@cn";
var actual = AQL_EXECUTE(q, { "@cn": cn1, "@e": cn3 });
assertEqual([ ], actual.json);
assertEqual(2009, actual.stats.writesExecuted);
assertEqual(1, c1.count());
assertTrue(c1.exists("1"));
assertEqual(2009, c3.count());
},
testTraversalAfterModification : function () {
var q = "INSERT { _key: '1', foo: 'bar' } INTO @@cn FOR doc IN OUTBOUND 'v/1' @@e RETURN doc";
assertQueryError(errors.ERROR_QUERY_ACCESS_AFTER_MODIFICATION.code, q, { "@cn": cn1, "@e": cn3 });