mirror of https://gitee.com/bigwinds/arangodb
fixed issue #1950
This commit is contained in:
parent
f038fa386f
commit
8369f652a4
|
@ -1239,12 +1239,12 @@ class arangodb::aql::RedundantCalculationsReplacer final
|
|||
public:
|
||||
explicit RedundantCalculationsReplacer(
|
||||
std::unordered_map<VariableId, Variable const*> const& replacements)
|
||||
: _replacements(replacements) {}
|
||||
: _replacements(replacements) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void replaceInVariable(ExecutionNode* en) {
|
||||
auto node = static_cast<T*>(en);
|
||||
|
||||
node->_inVariable = Variable::replace(node->_inVariable, _replacements);
|
||||
}
|
||||
|
||||
|
@ -1252,7 +1252,7 @@ class arangodb::aql::RedundantCalculationsReplacer final
|
|||
auto node = static_cast<CalculationNode*>(en);
|
||||
std::unordered_set<Variable const*> variables;
|
||||
node->expression()->variables(variables);
|
||||
|
||||
|
||||
// check if the calculation uses any of the variables that we want to
|
||||
// replace
|
||||
for (auto const& it : variables) {
|
||||
|
@ -3784,6 +3784,14 @@ void arangodb::aql::inlineSubqueriesRule(Optimizer* opt,
|
|||
auto queryVariables = plan->getAst()->variables();
|
||||
std::vector<ExecutionNode*> subNodes(subqueryNode->getSubquery()->getDependencyChain(true));
|
||||
|
||||
// check if the subquery result variable is used after the FOR loop as well
|
||||
std::unordered_set<Variable const*> varsUsedLater(listNode->getVarsUsedLater());
|
||||
if (varsUsedLater.find(listNode->inVariable()) != varsUsedLater.end()) {
|
||||
// exit the loop
|
||||
current = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
TRI_ASSERT(! subNodes.empty());
|
||||
auto returnNode = static_cast<ReturnNode*>(subNodes[0]);
|
||||
TRI_ASSERT(returnNode->getType() == EN::RETURN);
|
||||
|
|
|
@ -469,6 +469,12 @@ function removeClusterNodes (nodeTypes) {
|
|||
});
|
||||
}
|
||||
|
||||
function removeClusterNodesFromPlan (nodes) {
|
||||
return nodes.filter(function (node) {
|
||||
return ([ 'ScatterNode', 'GatherNode', 'DistributeNode', 'RemoteNode' ].indexOf(node.type) === -1);
|
||||
});
|
||||
}
|
||||
|
||||
exports.isEqual = isEqual;
|
||||
exports.getParseResults = getParseResults;
|
||||
exports.assertParseError = assertParseError;
|
||||
|
@ -487,3 +493,4 @@ exports.findReferencedNodes = findReferencedNodes;
|
|||
exports.getQueryMultiplePlansAndExecutions = getQueryMultiplePlansAndExecutions;
|
||||
exports.removeAlwaysOnClusterRules = removeAlwaysOnClusterRules;
|
||||
exports.removeClusterNodes = removeClusterNodes;
|
||||
exports.removeClusterNodesFromPlan = removeClusterNodesFromPlan;
|
||||
|
|
|
@ -31,14 +31,14 @@
|
|||
var jsunity = require("jsunity");
|
||||
var helper = require("@arangodb/aql-helper");
|
||||
var isEqual = helper.isEqual;
|
||||
var db = require("@arangodb").db;
|
||||
var ruleName = "inline-subqueries";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function optimizerRuleTestSuite () {
|
||||
var ruleName = "inline-subqueries";
|
||||
|
||||
// various choices to control the optimizer:
|
||||
var paramNone = { optimizer: { rules: [ "-all" ] } };
|
||||
var paramEnabled = { optimizer: { rules: [ "-all", "+" + ruleName ] }, inspectSimplePlans: true };
|
||||
|
@ -161,8 +161,73 @@ function optimizerRuleTestSuite () {
|
|||
result = AQL_EXECUTE(query[0]).json;
|
||||
assertEqual(query[1], result, query);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function optimizerRuleCollectionTestSuite () {
|
||||
var c = null;
|
||||
var cn = "UnitTestsOptimizer";
|
||||
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
setUp : function () {
|
||||
db._drop(cn);
|
||||
c = db._create(cn);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tear down
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tearDown : function () {
|
||||
db._drop(cn);
|
||||
c = null;
|
||||
},
|
||||
|
||||
testSpecificPlan1 : function () {
|
||||
var query = "LET x = (FOR doc IN @@cn RETURN doc) FOR doc2 IN x RETURN doc2";
|
||||
|
||||
var result = AQL_EXPLAIN(query, { "@cn" : cn });
|
||||
assertNotEqual(-1, result.plan.rules.indexOf(ruleName), query);
|
||||
var nodes = helper.removeClusterNodesFromPlan(result.plan.nodes);
|
||||
assertEqual(3, nodes.length);
|
||||
assertEqual("ReturnNode", nodes[nodes.length - 1].type);
|
||||
assertEqual("doc2", nodes[nodes.length - 1].inVariable.name);
|
||||
assertEqual("EnumerateCollectionNode", nodes[nodes.length - 2].type);
|
||||
assertEqual(cn, nodes[nodes.length - 2].collection);
|
||||
},
|
||||
|
||||
testSpecificPlan2 : function () {
|
||||
var query = "LET x = (FOR doc IN @@cn FILTER doc.foo == 'bar' RETURN doc) FOR doc2 IN x RETURN doc2";
|
||||
|
||||
var result = AQL_EXPLAIN(query, { "@cn" : cn });
|
||||
assertNotEqual(-1, result.plan.rules.indexOf(ruleName), query);
|
||||
var nodes = helper.removeClusterNodesFromPlan(result.plan.nodes);
|
||||
assertEqual(5, nodes.length);
|
||||
assertEqual("ReturnNode", nodes[nodes.length - 1].type);
|
||||
assertEqual("doc2", nodes[nodes.length - 1].inVariable.name);
|
||||
assertEqual("FilterNode", nodes[nodes.length - 2].type);
|
||||
assertEqual("CalculationNode", nodes[nodes.length - 3].type);
|
||||
assertEqual("EnumerateCollectionNode", nodes[nodes.length - 4].type);
|
||||
assertEqual(cn, nodes[nodes.length - 4].collection);
|
||||
},
|
||||
|
||||
testSpecificPlan3 : function () {
|
||||
var query = "LET x = (FOR doc IN @@cn RETURN doc) FOR doc2 IN x RETURN x";
|
||||
var result = AQL_EXPLAIN(query, { "@cn" : cn });
|
||||
assertEqual(-1, result.plan.rules.indexOf(ruleName), query); // no optimization
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -171,5 +236,6 @@ function optimizerRuleTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
jsunity.run(optimizerRuleTestSuite);
|
||||
jsunity.run(optimizerRuleCollectionTestSuite);
|
||||
|
||||
return jsunity.done();
|
||||
|
|
Loading…
Reference in New Issue