1
0
Fork 0
This commit is contained in:
Jan 2018-02-27 11:29:15 +01:00 committed by GitHub
parent f5f0b66c06
commit f74822483c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 1 deletions

View File

@ -1,6 +1,9 @@
v3.3.4 (XXXX-XX-XX)
-------------------
* fix issue #4677: AQL WITH with bind parameters results in "access after data-modification"
for two independent UPSERTs
* fix issue #4457: create /var/tmp/arangod with correct user in supervisor mode
* remove long disfunctional admin/long_echo handler

View File

@ -1700,7 +1700,7 @@ void Ast::validateAndOptimize() {
if (ctx->filterDepth >= 0) {
++ctx->filterDepth;
}
if (node->type == NODE_TYPE_FILTER) {
TRI_ASSERT(ctx->filterDepth == -1);
ctx->filterDepth = 0;
@ -1712,6 +1712,12 @@ void Ast::validateAndOptimize() {
// NOOPT will turn all function optimizations off
++(ctx->stopOptimizationRequests);
}
} else if (node->type == NODE_TYPE_COLLECTION_LIST) {
// a collection list is produced by WITH a, b, c
// or by traversal declarations
// we do not want to descend further, in order to not track
// the collections in collectionsFirstSeen
return false;
} else if (node->type == NODE_TYPE_COLLECTION) {
// note the level on which we first saw a collection
ctx->collectionsFirstSeen.emplace(node->getString(), ctx->nestingLevel);

View File

@ -120,6 +120,52 @@ function ahuacatlMultiModifySuite () {
assertTrue(found);
},
testWithDeclarationAndModification : function () {
var q = "WITH @@cn RETURN (INSERT {} INTO @@cn)";
var actual = AQL_EXECUTE(q, { "@cn": cn1 });
assertEqual([ [ ] ], actual.json);
assertEqual(1, actual.stats.writesExecuted);
assertEqual(1, c1.count());
assertEqual(0, c2.count());
},
testWithDeclarationsAndSingleModificationMultipleCollections : function () {
var q = "WITH @@cn1, @@cn2 RETURN (INSERT {} INTO @@cn1)";
var actual = AQL_EXECUTE(q, { "@cn1": cn1, "@cn2" : cn2 });
assertEqual([ [ ] ], actual.json);
assertEqual(1, actual.stats.writesExecuted);
assertEqual(1, c1.count());
assertEqual(0, c2.count());
},
testWithDeclarationsAndMultiModificationMultipleCollections : function () {
var q = "WITH @@cn1, @@cn2 RETURN [(INSERT {} INTO @@cn1), (INSERT {} INTO @@cn2)]";
var actual = AQL_EXECUTE(q, { "@cn1": cn1, "@cn2" : cn2 });
assertEqual([ [ [ ], [ ] ] ], actual.json);
assertEqual(2, actual.stats.writesExecuted);
assertEqual(1, c1.count());
assertEqual(1, c2.count());
},
testWithDeclarationsAndModificationWriteRead : function () {
var q = "WITH @@cn1, @@cn2 RETURN [(INSERT {} INTO @@cn1), (FOR doc IN @@cn2 RETURN doc)]";
var actual = AQL_EXECUTE(q, { "@cn1": cn1, "@cn2" : cn2 });
assertEqual([ [ [ ], [ ] ] ], actual.json);
assertEqual(1, actual.stats.writesExecuted);
assertEqual(1, c1.count());
assertEqual(0, c2.count());
},
testWithDeclarationSameCollectionWriteThenRead : function () {
var q = "WITH @@cn1 RETURN [(INSERT {} INTO @@cn1), (FOR doc IN @@cn1 RETURN doc)]";
assertQueryError(errors.ERROR_QUERY_ACCESS_AFTER_MODIFICATION.code, q, { "@cn1": cn1 });
},
testWithDeclarationAndModificationMultipleCollectionsThenRead : function () {
var q = "WITH @@cn1 LET x = (INSERT {} INTO @@cn1) FOR doc IN @@cn1 RETURN doc";
assertQueryError(errors.ERROR_QUERY_ACCESS_AFTER_MODIFICATION.code, q, { "@cn1": cn1 });
},
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 });