mirror of https://gitee.com/bigwinds/arangodb
parent
f5f0b66c06
commit
f74822483c
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 });
|
||||
|
|
Loading…
Reference in New Issue