mirror of https://gitee.com/bigwinds/arangodb
408 lines
26 KiB
JavaScript
408 lines
26 KiB
JavaScript
/*jshint globalstrict:false, strict:false, maxlen: 500 */
|
|
/*global assertTrue, assertEqual, AQL_EXECUTE, AQL_EXPLAIN */
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief tests for single operation nodes in cluster
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// @author Wilfried Goesgens
|
|
/// @author Copyright 2018, ArangoDB GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
var jsunity = require("jsunity");
|
|
var internal = require("internal");
|
|
var errors = internal.errors;
|
|
var db = require("@arangodb").db;
|
|
var helper = require("@arangodb/aql-helper");
|
|
var assertQueryError = helper.assertQueryError;
|
|
const isCluster = require("@arangodb/cluster").isCluster();
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief test suite
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function optimizerClusterSingleDocumentTestSuite () {
|
|
var ruleName = "optimize-cluster-single-document-operations";
|
|
// various choices to control the optimizer:
|
|
var thisRuleEnabled = { optimizer: { rules: [ "+all" ] } }; // we can only work after other rules
|
|
var thisRuleDisabled = { optimizer: { rules: [ "+all", "-" + ruleName ] } };
|
|
var notHereDoc = "notHereDoc";
|
|
var yeOldeDoc = "yeOldeDoc";
|
|
|
|
var cn1 = "UnitTestsCollection";
|
|
var c1;
|
|
|
|
var cn2 = "UnitTestsCollectionEmty";
|
|
var c2;
|
|
|
|
var cn3 = "UnitTestsCollectionModify";
|
|
var c3;
|
|
|
|
var s = function() {};
|
|
|
|
var setupC1 = function() {
|
|
db._drop(cn1);
|
|
c1 = db._create(cn1, { numberOfShards: 5 });
|
|
|
|
for (var i = 0; i < 20; ++i) {
|
|
c1.save({ _key: `${i}`, group: "test" + (i % 10), value1: i, value2: i % 5 });
|
|
}
|
|
};
|
|
|
|
var setupC2 = function() {
|
|
db._drop(cn2);
|
|
c2 = db._create(cn2, { numberOfShards: 5 });
|
|
c2.save({_key: yeOldeDoc});
|
|
};
|
|
|
|
var setupC3 = function() {
|
|
db._drop(cn3);
|
|
c3 = db._create(cn3, { numberOfShards: 5 });
|
|
|
|
for (var i = 0; i < 20; ++i) {
|
|
c3.save({ _key: `${i}`, group: "test" + (i % 10), value1: i, value2: i % 5 });
|
|
}
|
|
};
|
|
|
|
var pruneRevisions = function(obj) {
|
|
if (typeof obj instanceof Array) {
|
|
obj.forEach(function (doc) { pruneRevisions(doc);});
|
|
} else {
|
|
if ((obj !== null) && (typeof obj !== "string")) {
|
|
if (obj instanceof Object) {
|
|
if (obj.hasOwnProperty('_rev')) {
|
|
obj._rev = "wedontcare";
|
|
}
|
|
for (var property in obj) {
|
|
if (!obj.hasOwnProperty(property)) continue;
|
|
pruneRevisions(obj[property]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var explain = function (result) {
|
|
return helper.getCompactPlan(result).map(function(node)
|
|
{ return node.type; });
|
|
};
|
|
var runTestSet = function(sets, expectedRules, expectedNodes) {
|
|
let count = 0;
|
|
sets.forEach(function(set) {
|
|
let queryString = set[0];
|
|
let expectRule = expectedRules[set[1]];
|
|
let expectNode = expectedNodes[set[2]];
|
|
let doFullTest = set[3]; // Do advanced checking
|
|
let setupFunction = set[4]; // this resets the setup
|
|
let errorCode = set[5]; // expected error code
|
|
const queryInfo = "count: " + count + " query info: " + JSON.stringify(set);
|
|
|
|
var result = AQL_EXPLAIN(queryString, { }, thisRuleEnabled); // explain - only
|
|
assertEqual(expectRule, result.plan.rules, "rules mismatch: " + queryInfo);
|
|
assertEqual(expectNode, explain(result), "nodes mismatch: " + queryInfo);
|
|
if (doFullTest) {
|
|
var r1 = {json: []}, r2 = {json: []};
|
|
|
|
// run it first without the rule
|
|
setupFunction();
|
|
try {
|
|
r1 = AQL_EXECUTE(queryString, {}, thisRuleDisabled);
|
|
assertEqual(0, errorCode, "we have no error in the original, but the tests expects an exception: " + queryInfo);
|
|
}
|
|
catch (y) {
|
|
assertTrue(errorCode.hasOwnProperty('code'), "original plan throws, but we don't expect an exception" + JSON.stringify(y) + queryInfo);
|
|
assertEqual(y.errorNum, errorCode.code, "match other error code - got: " + JSON.stringify(y) + queryInfo);
|
|
}
|
|
|
|
// Run it again with our rule
|
|
setupFunction();
|
|
try {
|
|
r2 = AQL_EXECUTE(queryString, {}, thisRuleEnabled);
|
|
assertEqual(0, errorCode, "we have no error in our plan, but the tests expects an exception" + queryInfo);
|
|
}
|
|
catch (x) {
|
|
assertTrue(errorCode.hasOwnProperty('code'), "our plan throws, but we don't expect an exception" + JSON.stringify(x) + queryInfo);
|
|
assertEqual(x.errorNum, errorCode.code, "match our error code" + JSON.stringify(x) + queryInfo);
|
|
}
|
|
pruneRevisions(r1);
|
|
pruneRevisions(r2);
|
|
assertEqual(r1.json, r2.json, "results of with and without rule differ: " + queryInfo);
|
|
}
|
|
count += 1;
|
|
});
|
|
};
|
|
|
|
return {
|
|
setUp : function () {
|
|
setupC1();
|
|
setupC2();
|
|
setupC3();
|
|
},
|
|
|
|
tearDown : function () {
|
|
db._drop(cn1);
|
|
db._drop(cn2);
|
|
db._drop(cn3);
|
|
},
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief test plans that should result
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
testRuleFetch : function () {
|
|
var queries = [
|
|
[ "FOR d IN " + cn1 + " FILTER d._key == '1' RETURN d", 0, 0, true, s, 0],
|
|
[ "FOR d IN " + cn1 + " FILTER '1' == d._key RETURN d", 0, 0, true, s, 0],
|
|
[ "FOR d IN " + cn1 + " FILTER d.xyz == '1' RETURN d", 1, 1, false, s, 0],
|
|
[ "FOR d IN " + cn1 + " FILTER d._key == '1' RETURN 123", 2, 2, true, s, 0],
|
|
[ "FOR d IN " + cn1 + " FILTER d._key == '1' LIMIT 10, 1 RETURN d", 3, 3, false, s, 0],
|
|
[ "FOR d IN " + cn1 + " FILTER d._key == '1' RETURN d._key", 4, 4, true, s, 0],
|
|
];
|
|
var expectedRules = [[ "use-indexes",
|
|
"remove-filter-covered-by-index",
|
|
"remove-unnecessary-calculations-2",
|
|
"optimize-cluster-single-document-operations" ],
|
|
[ "scatter-in-cluster",
|
|
"distribute-filtercalc-to-cluster",
|
|
"remove-unnecessary-remote-scatter" ],
|
|
[ "move-calculations-up",
|
|
"use-indexes",
|
|
"remove-filter-covered-by-index",
|
|
"remove-unnecessary-calculations-2",
|
|
"optimize-cluster-single-document-operations" ],
|
|
[ "use-indexes", "remove-filter-covered-by-index",
|
|
"remove-unnecessary-calculations-2",
|
|
"scatter-in-cluster", "remove-unnecessary-remote-scatter",
|
|
"restrict-to-single-shard"],
|
|
[ "move-calculations-up",
|
|
"move-filters-up",
|
|
"move-calculations-up-2",
|
|
"move-filters-up-2",
|
|
"use-indexes",
|
|
"remove-filter-covered-by-index",
|
|
"remove-unnecessary-calculations-2",
|
|
"optimize-cluster-single-document-operations" ],
|
|
];
|
|
|
|
var expectedNodes = [
|
|
[ "SingletonNode", "SingleRemoteOperationNode", "ReturnNode" ],
|
|
[ "SingletonNode", "EnumerateCollectionNode", "CalculationNode",
|
|
"FilterNode", "RemoteNode", "GatherNode", "ReturnNode" ],
|
|
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode",
|
|
"ReturnNode"],
|
|
[ "SingletonNode", "IndexNode", "RemoteNode", "GatherNode", "LimitNode", "ReturnNode" ],
|
|
[ "SingletonNode", "SingleRemoteOperationNode", "CalculationNode", "ReturnNode" ],
|
|
];
|
|
runTestSet(queries, expectedRules, expectedNodes);
|
|
},
|
|
|
|
testRuleInsert : function () {
|
|
var queries = [
|
|
// [ query, expectedRulesField, expectedNodesField, doFullTest, setupFunction, errorCode ]
|
|
[ `INSERT {_key: '${notHereDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, ignoreErrors:true}`, 0, 0, true, setupC2, 0 ],
|
|
[ `INSERT {_key: '${yeOldeDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, ignoreErrors:true}`, 0, 0, true, setupC2, 0 ],
|
|
|
|
[ `INSERT {_key: '${notHereDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, overwrite: true} RETURN OLD`, 0, 1, true, setupC2, 0 ],
|
|
[ `INSERT {_key: '${yeOldeDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, overwrite: true} RETURN OLD`, 0, 1, true, setupC2, 0 ],
|
|
|
|
[ `INSERT {_key: '${notHereDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, overwrite: true} RETURN NEW`, 0, 1, true, setupC2, 0 ],
|
|
[ `INSERT {_key: '${yeOldeDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, overwrite: true} RETURN NEW`, 0, 1, true, setupC2, 0 ],
|
|
|
|
[ `INSERT {_key: '${notHereDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, overwrite: false} RETURN NEW`, 0, 1, true, setupC2, 0 ],
|
|
[ `INSERT {_key: '${yeOldeDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, overwrite: false} RETURN NEW`, 0, 1, true, setupC2, errors.ERROR_ARANGO_UNIQUE_CONSTRAINT_VIOLATED],
|
|
|
|
[ `INSERT {_key: '${yeOldeDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, overwrite: true} RETURN [OLD, NEW]`, 1, 2, true, setupC2, 0 ],
|
|
[ `INSERT {_key: '${yeOldeDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, overwrite: true} RETURN { old: OLD, new: NEW }`, 1, 2, true, setupC2, 0 ],
|
|
[ `LET a = { a: 123 } INSERT {_key: '${notHereDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, overwrite: true} RETURN [OLD, NEW, a]`, 2, 2, true, setupC2, 0 ],
|
|
[ `LET a = { a: 123 } INSERT {_key: '${yeOldeDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, overwrite: true} RETURN { old: OLD, new: NEW, a: a }`, 2, 2, true, setupC2, 0 ],
|
|
[ `LET a = { a: 123 } INSERT {_key: '${notHereDoc}', insert1: true} IN ${cn2} OPTIONS {waitForSync: true, overwrite: true} RETURN a`, 3, 3, true, setupC2, 0 ],
|
|
[ `INSERT {_key: '${notHereDoc}', insert1: true} IN ${cn2} RETURN NEW`, 0, 1, true, setupC2, 0 ],
|
|
[ `INSERT {_key: '${notHereDoc}', insert1: true} IN ${cn2} RETURN NEW._key`, 0, 2, true, setupC2, 0 ],
|
|
];
|
|
|
|
var expectedRules = [
|
|
[ "remove-data-modification-out-variables", "optimize-cluster-single-document-operations" ],
|
|
[ "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "remove-unnecessary-calculations", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "remove-redundant-calculations", "remove-unnecessary-calculations", "move-calculations-up-2",
|
|
"remove-data-modification-out-variables", "optimize-cluster-single-document-operations" ]
|
|
];
|
|
var expectedNodes = [
|
|
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode" ],
|
|
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode", "ReturnNode" ],
|
|
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode", "CalculationNode", "ReturnNode" ],
|
|
[ "SingletonNode", "CalculationNode", "CalculationNode", "SingleRemoteOperationNode", "ReturnNode" ]
|
|
];
|
|
|
|
runTestSet(queries, expectedRules, expectedNodes);
|
|
},
|
|
|
|
testRuleUpdate : function () {
|
|
var queries = [
|
|
[ "UPDATE {_key: '1'} IN " + cn1 + " OPTIONS {}", 0, 0, true, s, 0],
|
|
[ "UPDATE {_key: '1'} INTO " + cn1 + " OPTIONS {}", 0, 0, true, s, 0],
|
|
[ "UPDATE {_key: '1'} IN " + cn1 + " OPTIONS {} RETURN OLD", 0, 1, true, s, 0],
|
|
[ "UPDATE {_key: '1'} INTO " + cn1 + " OPTIONS {} RETURN OLD", 0, 1, true, s, 0],
|
|
[ "UPDATE {_key: '1'} IN " + cn1 + " OPTIONS {} RETURN NEW", 0, 1, true, s, 0],
|
|
[ "UPDATE {_key: '1'} INTO " + cn1 + " OPTIONS {} RETURN NEW", 0, 1, true, s, 0],
|
|
[ "UPDATE {_key: '1'} IN " + cn1 + " OPTIONS {} RETURN [OLD, NEW]", 3, 2, false],
|
|
[ "UPDATE {_key: '1'} INTO " + cn1 + " OPTIONS {} RETURN [OLD, NEW]", 3, 2, false],
|
|
[ "UPDATE {_key: '1'} IN " + cn1 + " OPTIONS {} RETURN { old: OLD, new: NEW }", 3, 2, false],
|
|
[ "UPDATE {_key: '1'} INTO " + cn1 + " OPTIONS {} RETURN { old: OLD, new: NEW }", 3, 2, false],
|
|
[ "UPDATE {_key: '1', boom: true } INTO " + cn1 + " OPTIONS {} RETURN { old: OLD, new: NEW }", 3, 2, true, setupC1, 0],
|
|
[ "UPDATE {_key: '1'} WITH {foo: 'bar1a'} IN " + cn1 + " OPTIONS {}", 1, 0, true, s, 0],
|
|
[ "UPDATE {_key: '1'} WITH {foo: 'bar2a'} IN " + cn1 + " OPTIONS {} RETURN OLD", 1, 1, true, setupC1, 0],
|
|
[ "UPDATE {_key: '1'} WITH {foo: 'bar3a'} IN " + cn1 + " OPTIONS {} RETURN NEW", 1, 1, true, s, 0],
|
|
[ "UPDATE {_key: '1'} WITH {foo: 'bar4a'} IN " + cn1 + " OPTIONS {} RETURN [OLD, NEW]", 2, 2, true, setupC1, 0],
|
|
[ "UPDATE {_key: '1'} WITH {foo: 'bar5a'} IN " + cn1 + " OPTIONS {} RETURN { old: OLD, new: NEW }", 2, 2, true, setupC1, 0],
|
|
[ "UPDATE {_key: '1'} INTO " + cn1 + " RETURN OLD._key", 0, 2, true, s, 0],
|
|
[ `FOR doc IN ${cn1} FILTER doc._key == '1' UPDATE doc INTO ${cn1} OPTIONS {} RETURN NEW`, 4, 3, true, s, 0],
|
|
[ `FOR doc IN ${cn1} FILTER doc._key == '1' UPDATE doc WITH {foo: 'bar'} INTO ${cn1} OPTIONS {} RETURN [OLD, NEW]`, 8, 2, true, setupC1, 0],
|
|
[ `FOR doc IN ${cn1} FILTER doc._key == '${notHereDoc}' UPDATE doc WITH {foo: 'bar'} INTO ${cn1} OPTIONS {} RETURN [OLD, NEW]`, 8, 2, true, setupC1, 0],
|
|
[ `LET a = { a: 123 } FOR doc IN ${cn1} FILTER doc._key == '1' UPDATE doc INTO ${cn1} OPTIONS {} RETURN { NEW: NEW, a: a }`, 6, 4, true, s, 0],
|
|
[ `LET a = { a: 123 } FOR doc IN ${cn1} FILTER doc._key == '1' UPDATE doc WITH {foo: 'bar'} INTO ${cn1} OPTIONS {} RETURN [OLD, NEW, a]`, 9, 2, true, setupC1, 0],
|
|
[ `LET a = { a: 123 } FOR doc IN ${cn1} FILTER doc._key == '1' UPDATE doc INTO ${cn1} OPTIONS {} RETURN [ NEW, a ]`, 6, 4, true, s, 0],
|
|
[ `LET a = { a: 123 } FOR doc IN ${cn1} FILTER doc._key == '1' UPDATE doc WITH {foo: 'bar'} INTO ${cn1} OPTIONS {} RETURN [OLD, NEW, a]`, 9, 2, true, setupC1, 0],
|
|
[ `LET a = { a: 123 } FOR doc IN ${cn1} FILTER doc._key == '1' UPDATE doc WITH {foo: 'bar'} INTO ${cn1} OPTIONS {} RETURN [doc, NEW, a]`, 9, 2, true, setupC1, 0],
|
|
[ `FOR doc IN ${cn1} FILTER doc._key == '1' UPDATE doc WITH {foo: 'bar'} INTO ${cn1} RETURN OLD._key`, 8, 2, true, setupC1, 0],
|
|
];
|
|
|
|
var expectedRules = [
|
|
[ "remove-data-modification-out-variables", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "move-calculations-up-2", "remove-data-modification-out-variables", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "move-calculations-up-2", "optimize-cluster-single-document-operations" ],
|
|
[ "optimize-cluster-single-document-operations" ],
|
|
[ "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "remove-unnecessary-calculations", "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "remove-unnecessary-calculations", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "remove-unnecessary-calculations", "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
];
|
|
|
|
var expectedNodes = [
|
|
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode" ],
|
|
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode", "ReturnNode" ],
|
|
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode", "CalculationNode", "ReturnNode" ],
|
|
[ "SingletonNode", "SingleRemoteOperationNode", "ReturnNode" ],
|
|
[ "SingletonNode", "SingleRemoteOperationNode", "CalculationNode", "ReturnNode" ]
|
|
|
|
];
|
|
|
|
runTestSet(queries, expectedRules, expectedNodes);
|
|
},
|
|
|
|
testRuleReplace : function () {
|
|
var queries = [
|
|
[ "REPLACE {_key: '1'} IN " + cn1 + " OPTIONS {}", 0, 0, true, s, 0],
|
|
[ "REPLACE {_key: '1'} INTO " + cn1 + " OPTIONS {}", 0, 0, true, s, 0],
|
|
[ "REPLACE {_key: '1'} IN " + cn1 + " OPTIONS {} RETURN OLD", 0, 1, true, s, 0],
|
|
[ "REPLACE {_key: '1'} INTO " + cn1 + " OPTIONS {} RETURN OLD", 0, 1, true, s, 0],
|
|
[ "REPLACE {_key: '1'} IN " + cn1 + " OPTIONS {} RETURN NEW", 0, 1, true, s, 0],
|
|
[ "REPLACE {_key: '1'} INTO " + cn1 + " OPTIONS {} RETURN NEW", 0, 1, true, s, 0],
|
|
[ "REPLACE {_key: '1'} IN " + cn1 + " OPTIONS {} RETURN [OLD, NEW]", 3, 2, false],
|
|
[ "REPLACE {_key: '1'} INTO " + cn1 + " OPTIONS {} RETURN [OLD, NEW]", 3, 2, false],
|
|
[ "REPLACE {_key: '1'} IN " + cn1 + " OPTIONS {} RETURN { old: OLD, new: NEW }", 3, 2, false],
|
|
[ "REPLACE {_key: '1'} INTO " + cn1 + " OPTIONS {} RETURN { old: OLD, new: NEW }", 3, 2, false],
|
|
[ "REPLACE {_key: '1'} WITH {foo: 'bar1a'} IN " + cn1 + " OPTIONS {}", 1, 0, true, s, 0],
|
|
[ "REPLACE {_key: '1'} WITH {foo: 'bar2a'} IN " + cn1 + " OPTIONS {} RETURN OLD", 1, 1, true, setupC1, 0],
|
|
[ "REPLACE {_key: '1'} WITH {foo: 'bar2a'} IN " + cn1 + " OPTIONS {} RETURN OLD._key", 10, 2, true, setupC1, 0],
|
|
[ "REPLACE {_key: '1'} WITH {foo: 'bar3a'} IN " + cn1 + " OPTIONS {} RETURN NEW", 1, 1, true, s, 0],
|
|
[ "REPLACE {_key: '1'} WITH {foo: 'bar4a'} IN " + cn1 + " OPTIONS {} RETURN [OLD, NEW]", 2, 2, true, setupC1, 0],
|
|
[ "REPLACE {_key: '1', boom: true } IN " + cn1 + " OPTIONS {} RETURN [OLD, NEW]", 3, 2, true, setupC1, 0],
|
|
[ "REPLACE {_key: '1'} WITH {foo: 'bar5a'} IN " + cn1 + " OPTIONS {} RETURN { old: OLD, new: NEW }", 2, 2, true, setupC1, 0],
|
|
[ `FOR doc IN ${cn1} FILTER doc._key == '1' REPLACE doc WITH {foo: 'bar'} INTO ${cn1} OPTIONS {} RETURN [OLD, NEW]`, 8, 2, true, setupC1, 0],
|
|
[ `FOR doc IN ${cn1} FILTER doc._key == '1' REPLACE doc INTO ${cn1} OPTIONS {} RETURN NEW`, 4, 3, true, setupC1, 0],
|
|
|
|
[ `LET a = 123 FOR doc IN ${cn1} FILTER doc._key == '-1' REPLACE doc WITH {foo: 'bar'} INTO ${cn1} OPTIONS {} RETURN [OLD, NEW, a]`, 9, 2, true, setupC1, 0 ],
|
|
|
|
[ `LET a = 123 FOR doc IN ${cn1} FILTER doc._key == '1' REPLACE doc WITH {foo: 'bar'} INTO ${cn1} OPTIONS {} RETURN [OLD, NEW, a]`, 9, 2, true, setupC1, 0],
|
|
[ `LET a = 123 FOR doc IN ${cn1} FILTER doc._key == '1' REPLACE doc WITH {foo: 'bar'} INTO ${cn1} OPTIONS {} RETURN [doc, NEW, a]`, 9, 2, true, setupC1, 0],
|
|
[ `LET a = 123 FOR doc IN ${cn1} FILTER doc._key == '1' REPLACE doc INTO ${cn1} OPTIONS {} RETURN [ NEW, a ]`, 7, 4, true, setupC1, 0],
|
|
[ `FOR doc IN ${cn1} FILTER doc._key == '1' REPLACE doc INTO ${cn1} RETURN OLD._key`, 4, 4, true, setupC1, 0],
|
|
];
|
|
|
|
var expectedRules = [
|
|
[ "remove-data-modification-out-variables", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "move-calculations-up-2", "remove-data-modification-out-variables", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "move-calculations-up-2", "optimize-cluster-single-document-operations" ],
|
|
[ "optimize-cluster-single-document-operations" ],
|
|
[ "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "remove-unnecessary-calculations", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "remove-unnecessary-calculations", "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "remove-unnecessary-calculations", "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "move-calculations-up-2", "remove-data-modification-out-variables", "optimize-cluster-single-document-operations" ],
|
|
];
|
|
|
|
var expectedNodes = [
|
|
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode" ],
|
|
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode", "ReturnNode" ],
|
|
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode", "CalculationNode", "ReturnNode"],
|
|
[ "SingletonNode", "SingleRemoteOperationNode", "ReturnNode" ],
|
|
[ "SingletonNode", "SingleRemoteOperationNode", "CalculationNode", "ReturnNode" ]
|
|
];
|
|
|
|
runTestSet(queries, expectedRules, expectedNodes);
|
|
},
|
|
|
|
testRuleRemove : function () {
|
|
var queries = [
|
|
[ "REMOVE {_key: '1'} IN " + cn1 + " OPTIONS {}", 0, 0, true, setupC1, 0],
|
|
[ "REMOVE {_key: '2'} INTO " + cn1 + " OPTIONS {}", 0, 0, true, setupC1, 0],
|
|
[ "REMOVE {_key: '3'} IN " + cn1 + " OPTIONS {} RETURN OLD", 0, 1, true, setupC1, 0],
|
|
[ "REMOVE {_key: '4'} INTO " + cn1 + " OPTIONS {} RETURN OLD", 0, 1, true, setupC1, 0],
|
|
[ "REMOVE {_key: '4'} INTO " + cn1 + " RETURN OLD._key", 0, 2, true, setupC1, 0],
|
|
[ `FOR doc IN ${cn1} FILTER doc._key == '1' REMOVE doc IN ${cn1} RETURN OLD`, 1, 1, true, setupC1, 0],
|
|
[ `FOR doc IN ${cn1} FILTER doc._key == 'notheredoc' REMOVE doc IN ${cn1} RETURN OLD`, 1, 1, true, s, 0],
|
|
[ `LET a = 123 FOR doc IN ${cn1} FILTER doc._key == '1' REMOVE doc IN ${cn1} RETURN [OLD, a]`, 2, 2, true, setupC1, 0],
|
|
[ `LET a = 123 FOR doc IN ${cn1} FILTER doc._key == 'notheredoc' REMOVE doc IN ${cn1} RETURN [OLD, a]`, 2, 2, true, s, 0],
|
|
[ `LET a = 123 FOR doc IN ${cn1} FILTER doc._key == 'notheredoc' REMOVE doc IN ${cn1} RETURN a`, 3, 3, true, s, 0],
|
|
[ `LET a = 123 FOR doc IN ${cn1} FILTER doc._key == 'notheredoc' REMOVE doc IN ${cn1} RETURN doc`, 4, 1, true, s, 0],
|
|
[ `LET a = 123 FOR doc IN ${cn1} FILTER doc._key == 'notheredoc' REMOVE doc IN ${cn1} RETURN OLD`, 2, 1, true, s, 0],
|
|
[ `LET a = 123 FOR doc IN ${cn1} FILTER doc._key == 'notheredoc' REMOVE doc IN ${cn1} RETURN OLD._key`, 4, 2, true, s, 0],
|
|
[ `FOR doc IN ${cn1} FILTER doc._key == 'notheredoc' REMOVE doc IN ${cn1} RETURN OLD._key`, 1, 2, true, s, 0],
|
|
];
|
|
var expectedRules = [
|
|
[ "remove-data-modification-out-variables", "optimize-cluster-single-document-operations" ],
|
|
[ "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "remove-unnecessary-calculations", "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "move-calculations-up", "remove-redundant-calculations", "remove-unnecessary-calculations", "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
[ "remove-unnecessary-calculations", "remove-data-modification-out-variables", "use-indexes", "remove-filter-covered-by-index", "remove-unnecessary-calculations-2", "optimize-cluster-single-document-operations" ],
|
|
];
|
|
|
|
var expectedNodes = [
|
|
[ "SingletonNode", "SingleRemoteOperationNode" ],
|
|
[ "SingletonNode", "SingleRemoteOperationNode", "ReturnNode" ],
|
|
[ "SingletonNode", "SingleRemoteOperationNode", "CalculationNode", "ReturnNode" ],
|
|
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode", "ReturnNode" ],
|
|
];
|
|
|
|
runTestSet(queries, expectedRules, expectedNodes);
|
|
}
|
|
};
|
|
}
|
|
jsunity.run(optimizerClusterSingleDocumentTestSuite);
|
|
|
|
return jsunity.done();
|