mirror of https://gitee.com/bigwinds/arangodb
fixes for traversal and multi-modify
This commit is contained in:
parent
0a678263fb
commit
ee6792dd6b
|
@ -123,7 +123,8 @@ Ast::Ast (Query* query)
|
||||||
_root(nullptr),
|
_root(nullptr),
|
||||||
_queries(),
|
_queries(),
|
||||||
_writeCollections(),
|
_writeCollections(),
|
||||||
_functionsMayAccessDocuments(false) {
|
_functionsMayAccessDocuments(false),
|
||||||
|
_containsTraversal(false) {
|
||||||
|
|
||||||
TRI_ASSERT(_query != nullptr);
|
TRI_ASSERT(_query != nullptr);
|
||||||
|
|
||||||
|
@ -1230,6 +1231,8 @@ AstNode* Ast::createNodeTraversal (char const* vertexVarName,
|
||||||
|
|
||||||
TRI_ASSERT(node->numMembers() == 4);
|
TRI_ASSERT(node->numMembers() == 4);
|
||||||
|
|
||||||
|
_containsTraversal = true;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1253,6 +1256,8 @@ AstNode* Ast::createNodeTraversal (char const* vertexVarName,
|
||||||
node->addMember(edgeVar);
|
node->addMember(edgeVar);
|
||||||
|
|
||||||
TRI_ASSERT(node->numMembers() == 5);
|
TRI_ASSERT(node->numMembers() == 5);
|
||||||
|
|
||||||
|
_containsTraversal = true;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -1280,6 +1285,8 @@ AstNode* Ast::createNodeTraversal (char const* vertexVarName,
|
||||||
node->addMember(pathVar);
|
node->addMember(pathVar);
|
||||||
|
|
||||||
TRI_ASSERT(node->numMembers() == 6);
|
TRI_ASSERT(node->numMembers() == 6);
|
||||||
|
|
||||||
|
_containsTraversal = true;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,14 @@ namespace triagens {
|
||||||
return _functionsMayAccessDocuments;
|
return _functionsMayAccessDocuments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief whether or not the query contains a traversal
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool containsTraversal () const {
|
||||||
|
return _containsTraversal;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief convert the AST into JSON
|
/// @brief convert the AST into JSON
|
||||||
/// the caller is responsible for freeing the JSON later
|
/// the caller is responsible for freeing the JSON later
|
||||||
|
@ -998,6 +1006,12 @@ namespace triagens {
|
||||||
|
|
||||||
bool _functionsMayAccessDocuments;
|
bool _functionsMayAccessDocuments;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief whether or not the query contains a traversal
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool _containsTraversal;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief a singleton no-op node instance
|
/// @brief a singleton no-op node instance
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -471,12 +471,18 @@ ModificationOptions ExecutionPlan::createModificationOptions (AstNode const* nod
|
||||||
// no functions in the query can access document data...
|
// no functions in the query can access document data...
|
||||||
bool isReadWrite = false;
|
bool isReadWrite = false;
|
||||||
|
|
||||||
auto const collections = _ast->query()->collections();
|
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())) {
|
for (auto const& it : *(collections->collections())) {
|
||||||
if (it.second->isReadWrite) {
|
if (it.second->isReadWrite) {
|
||||||
isReadWrite = true;
|
isReadWrite = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3686,6 +3686,12 @@ int triagens::aql::patchUpdateStatementsRule (Optimizer* opt,
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == EN::TRAVERSAL) {
|
||||||
|
// unclear what will be read by the traversal
|
||||||
|
modified = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
dep = dep->getFirstDependency();
|
dep = dep->getFirstDependency();
|
||||||
}
|
}
|
||||||
|
|
|
@ -683,10 +683,16 @@ function processQuery (query, explain) {
|
||||||
}
|
}
|
||||||
rc += " " +
|
rc += " " +
|
||||||
keyword("IN") + " " +
|
keyword("IN") + " " +
|
||||||
node.minMaxDepth + " " + annotation("/* min..maxPathDepth */") + " " +
|
value(node.minMaxDepth) + " " + annotation("/* min..maxPathDepth */") + " " +
|
||||||
keyword("OUTBOUND") +
|
keyword("OUTBOUND") +
|
||||||
" '" + node.vertexId + "' " + annotation("/* Startnode */") + " " +
|
" '" + value(node.vertexId) + "' " + annotation("/* startnode */") + " ";
|
||||||
keyword("GRAPH") + " '" + node.graph + "'";
|
|
||||||
|
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);
|
traversalDetails.push(node);
|
||||||
if (node.hasOwnProperty('simpleExpressions')) {
|
if (node.hasOwnProperty('simpleExpressions')) {
|
||||||
|
|
|
@ -73,6 +73,43 @@ function ahuacatlMultiModifySuite () {
|
||||||
c3 = null;
|
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 () {
|
testTraversalAfterModification : function () {
|
||||||
var q = "INSERT { _key: '1', foo: 'bar' } INTO @@cn FOR doc IN OUTBOUND 'v/1' @@e RETURN doc";
|
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 });
|
assertQueryError(errors.ERROR_QUERY_ACCESS_AFTER_MODIFICATION.code, q, { "@cn": cn1, "@e": cn3 });
|
||||||
|
|
Loading…
Reference in New Issue