1
0
Fork 0

add more tests and improve queries a bit for single remote AQL operations (#7658)

This commit is contained in:
Jan 2018-12-05 17:37:25 +01:00 committed by GitHub
parent c245e9e230
commit 762c23bf77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 101 additions and 88 deletions

View File

@ -1675,7 +1675,7 @@ bool SingleRemoteOperationBlock::getOne(arangodb::aql::AqlItemBlock* aqlres,
opOptions.keepNull = !nodeOps.nullMeansRemove;
opOptions.mergeObjects = nodeOps.mergeObjects;
opOptions.returnNew = !!NEW;
opOptions.returnOld = !!OLD;
opOptions.returnOld = (!!OLD) || out;
opOptions.waitForSync = nodeOps.waitForSync;
opOptions.silent = false;
opOptions.overwrite = nodeOps.overwrite;
@ -1746,49 +1746,40 @@ bool SingleRemoteOperationBlock::getOne(arangodb::aql::AqlItemBlock* aqlres,
// only copy 1st row of registers inherited from previous frame(s)
TRI_ASSERT(result.ok());
VPackSlice outDocument = VPackSlice::noneSlice();
VPackSlice outDocument = VPackSlice::nullSlice();
if (result.buffer) {
outDocument = result.slice().resolveExternal();
}
VPackSlice oldDocument = VPackSlice::noneSlice();
VPackSlice newDocument = VPackSlice::noneSlice();
VPackSlice oldDocument = VPackSlice::nullSlice();
VPackSlice newDocument = VPackSlice::nullSlice();
if (outDocument.isObject()) {
if (outDocument.hasKey("old")){
oldDocument = outDocument.get("old");
}
if (outDocument.hasKey("new")){
if (NEW && outDocument.hasKey("new")) {
newDocument = outDocument.get("new");
}
if (outDocument.hasKey("old")) {
outDocument = outDocument.get("old");
if (OLD) {
oldDocument = outDocument;
}
}
}
TRI_ASSERT(out || OLD || NEW);
// place documents as in the out variable slots of the result
if (out) {
if (!outDocument.isNone()) {
aqlres->emplaceValue(outputCounter, static_cast<arangodb::aql::RegisterId>(outRegId), outDocument);
} else {
aqlres->emplaceValue(outputCounter, static_cast<arangodb::aql::RegisterId>(outRegId), VPackSlice::nullSlice());
}
aqlres->emplaceValue(outputCounter, static_cast<arangodb::aql::RegisterId>(outRegId), outDocument);
}
if (OLD) {
TRI_ASSERT(opOptions.returnOld);
if (!oldDocument.isNone()) {
aqlres->emplaceValue(outputCounter, static_cast<arangodb::aql::RegisterId>(oldRegId), oldDocument);
} else {
aqlres->emplaceValue(outputCounter, static_cast<arangodb::aql::RegisterId>(oldRegId), VPackSlice::nullSlice());
}
aqlres->emplaceValue(outputCounter, static_cast<arangodb::aql::RegisterId>(oldRegId), oldDocument);
}
if (NEW) {
TRI_ASSERT(opOptions.returnNew);
if (!newDocument.isNone()) {
aqlres->emplaceValue(outputCounter, static_cast<arangodb::aql::RegisterId>(newRegId), newDocument);
} else {
aqlres->emplaceValue(outputCounter, static_cast<arangodb::aql::RegisterId>(newRegId), VPackSlice::nullSlice());
}
aqlres->emplaceValue(outputCounter, static_cast<arangodb::aql::RegisterId>(newRegId), newDocument);
}
throwIfKilled(); // check if we were aborted

View File

@ -383,29 +383,28 @@ CostEstimate GatherNode::estimateCost() const {
return estimate;
}
SingleRemoteOperationNode::SingleRemoteOperationNode(ExecutionPlan* plan,
size_t id,
NodeType mode,
bool replaceIndexNode,
std::string const& key,
Collection const* collection,
ModificationOptions const& options,
Variable const* in,
Variable const* out,
Variable const* OLD,
Variable const* NEW
)
: ExecutionNode(plan, id)
, CollectionAccessingNode(collection)
, _replaceIndexNode(replaceIndexNode)
, _key(key)
, _mode(mode)
, _inVariable(in)
, _outVariable(out)
, _outVariableOld(OLD)
, _outVariableNew(NEW)
, _options(options)
{
SingleRemoteOperationNode::SingleRemoteOperationNode(
ExecutionPlan* plan,
size_t id,
NodeType mode,
bool replaceIndexNode,
std::string const& key,
Collection const* collection,
ModificationOptions const& options,
Variable const* in,
Variable const* out,
Variable const* OLD,
Variable const* NEW
) : ExecutionNode(plan, id),
CollectionAccessingNode(collection),
_replaceIndexNode(replaceIndexNode),
_key(key),
_mode(mode),
_inVariable(in),
_outVariable(out),
_outVariableOld(OLD),
_outVariableNew(NEW),
_options(options) {
if (_mode == NodeType::INDEX) { //select
TRI_ASSERT(!_key.empty());
TRI_ASSERT(_inVariable== nullptr);
@ -418,9 +417,7 @@ SingleRemoteOperationNode::SingleRemoteOperationNode(ExecutionPlan* plan,
TRI_ASSERT(_outVariableNew == nullptr);
} else if (_mode == NodeType::INSERT) {
TRI_ASSERT(_key.empty());
} else if (_mode == NodeType::UPDATE) {
} else if (_mode == NodeType::REPLACE) {
} else {
} else if (_mode != NodeType::UPDATE && _mode != NodeType::REPLACE) {
TRI_ASSERT(false);
}
}
@ -445,7 +442,7 @@ void SingleRemoteOperationNode::toVelocyPackHelper(VPackBuilder& nodes, unsigned
nodes.add("mode", VPackValue(ExecutionNode::getTypeString(_mode)));
nodes.add("replaceIndexNode", VPackValue(_replaceIndexNode));
if(!_key.empty()){
if (!_key.empty()) {
nodes.add("key", VPackValue(_key));
}

View File

@ -5872,10 +5872,7 @@ void arangodb::aql::removeDataModificationOutVariablesRule(
// "$OLD" is not used later
node->clearOutVariableOld();
modified = true;
#if 0
} else {
// TODO: activate this section once it does not cause problems with
// variables vanishing
switch (n->getType()) {
case EN::UPDATE:
case EN::REPLACE: {
@ -5909,7 +5906,6 @@ void arangodb::aql::removeDataModificationOutVariablesRule(
// do nothing
}
}
#endif
}
if (!n->isVarUsedLater(node->getOutVariableNew())) {

View File

@ -150,7 +150,7 @@ bool parentIsReturnOrConstCalc(ExecutionNode const* node) {
auto type = node->getType();
// we do not need to check the order because
// we expect a valid plan
if(type != EN::CALCULATION && type != EN::RETURN) {
if (type != EN::CALCULATION && type != EN::RETURN) {
return false;
}
node = node->getFirstParent();
@ -193,7 +193,7 @@ bool substituteClusterSingleDocumentOperationsIndex(Optimizer* opt,
if (!::depIsSingletonOrConstCalc(node)) {
continue;
}
Index* index = ::hasSingleIndexHandle(node, Index::TRI_IDX_TYPE_PRIMARY_INDEX);
if (index) {
IndexNode* indexNode = ExecutionNode::castTo<IndexNode*>(node);
@ -203,6 +203,8 @@ bool substituteClusterSingleDocumentOperationsIndex(Optimizer* opt,
continue;
}
TRI_ASSERT(node != nullptr);
auto* parentModification = ::hasSingleParent(node, {EN::INSERT, EN::REMOVE, EN::UPDATE, EN::REPLACE});
if (parentModification) {
@ -259,9 +261,9 @@ bool substituteClusterSingleDocumentOperationsIndex(Optimizer* opt,
modified = true;
} else if (::parentIsReturnOrConstCalc(node)) {
ExecutionNode* singleOperationNode = plan->registerNode(
new SingleRemoteOperationNode(plan, plan->nextId()
,EN::INDEX, true, key, indexNode->collection(), ModificationOptions{}
, nullptr /*in*/ , indexNode->outVariable() /*out*/, nullptr /*old*/, nullptr /*new*/)
new SingleRemoteOperationNode(plan, plan->nextId(),
EN::INDEX, true, key, indexNode->collection(), ModificationOptions{},
nullptr /*in*/ , indexNode->outVariable() /*out*/, nullptr /*old*/, nullptr /*new*/)
);
::replaceNode(plan, indexNode, singleOperationNode);
modified = true;

View File

@ -2,7 +2,7 @@
/*global assertTrue, assertEqual, AQL_EXECUTE, AQL_EXPLAIN */
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for COLLECT w/ COUNT
/// @brief tests for single operation nodes in cluster
///
/// @file
///
@ -175,6 +175,7 @@ function optimizerClusterSingleDocumentTestSuite () {
[ "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",
@ -191,7 +192,15 @@ function optimizerClusterSingleDocumentTestSuite () {
[ "use-indexes", "remove-filter-covered-by-index",
"remove-unnecessary-calculations-2",
"scatter-in-cluster", "remove-unnecessary-remote-scatter",
"restrict-to-single-shard"]
"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 = [
@ -200,7 +209,8 @@ function optimizerClusterSingleDocumentTestSuite () {
"FilterNode", "RemoteNode", "GatherNode", "ReturnNode" ],
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode",
"ReturnNode"],
[ "SingletonNode", "IndexNode", "RemoteNode", "GatherNode", "LimitNode", "ReturnNode" ]
[ "SingletonNode", "IndexNode", "RemoteNode", "GatherNode", "LimitNode", "ReturnNode" ],
[ "SingletonNode", "SingleRemoteOperationNode", "CalculationNode", "ReturnNode" ],
];
runTestSet(queries, expectedRules, expectedNodes);
},
@ -208,24 +218,25 @@ function optimizerClusterSingleDocumentTestSuite () {
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, 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 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: 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: '${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 ],
[ `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 = [
@ -246,7 +257,6 @@ function optimizerClusterSingleDocumentTestSuite () {
},
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],
@ -264,13 +274,16 @@ function optimizerClusterSingleDocumentTestSuite () {
[ "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]`, 5, 2, true, setupC1, 0],
[ `FOR doc IN ${cn1} FILTER doc._key == '${notHereDoc}' UPDATE doc WITH {foo: 'bar'} INTO ${cn1} OPTIONS {} RETURN [OLD, NEW]`, 5, 2, true, setupC1, 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]`, 7, 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 [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]`, 7, 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 [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 = [
@ -281,7 +294,9 @@ function optimizerClusterSingleDocumentTestSuite () {
[ "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-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 = [
@ -297,7 +312,6 @@ function optimizerClusterSingleDocumentTestSuite () {
},
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],
@ -311,17 +325,20 @@ function optimizerClusterSingleDocumentTestSuite () {
[ "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]`, 5, 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]`, 6, 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 [OLD, NEW, a]`, 6, 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 = [
@ -332,9 +349,12 @@ function optimizerClusterSingleDocumentTestSuite () {
[ "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" ]
[ "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" ],
@ -352,25 +372,32 @@ function optimizerClusterSingleDocumentTestSuite () {
[ "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" ]
[ "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" ]
[ "SingletonNode", "CalculationNode", "SingleRemoteOperationNode", "ReturnNode" ],
];
runTestSet(queries, expectedRules, expectedNodes);
}
};