1
0
Fork 0

fix execution of AQL traversal expressions when there are multiple conditions that refer to variables set outside the traversal

This commit is contained in:
Jan Steemann 2016-08-23 10:45:32 +02:00
parent d07c3c848c
commit 57fa55921c
5 changed files with 77 additions and 9 deletions

View File

@ -1,7 +1,7 @@
devel
-----
* added a memory expection of V8 memory gets to low
* added a memory expection in case V8 memory gets too low
* fixed epoch computation in hybrid logical clock
@ -43,7 +43,16 @@ devel
* added module.context.createDocumentationRouter to replace module.context.apiDocumentation
v3.0.5 (XXXX-XX-XX)
v3.0.6 (XXXX-XX-XX)
-------------------
* fix execution of AQL traversal expressions when there are multiple
conditions that refer to variables set outside the traversal
* properly return HTTP 503 in JS actions when backend is gone
v3.0.5 (2016-08-18)
-------------------
* execute AQL ternary operator via C++ if possible

View File

@ -844,6 +844,7 @@ AqlValue Expression::executeSimpleExpressionReference(
std::string msg("variable not found '");
msg.append(v->name);
msg.append("' in executeSimpleExpression()");
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, msg.c_str());
}

View File

@ -84,6 +84,14 @@ TraversalBlock::TraversalBlock(ExecutionEngine* engine, TraversalNode const* ep)
TRI_ASSERT(it->second.registerId < ExecutionNode::MaxRegisterId);
inRegsCur.emplace_back(it->second.registerId);
}
for (auto const& v : ep->_conditionVariables) {
inVarsCur.emplace_back(v);
auto it = ep->getRegisterPlan()->varInfo.find(v->id);
TRI_ASSERT(it != ep->getRegisterPlan()->varInfo.end());
TRI_ASSERT(it->second.registerId < ExecutionNode::MaxRegisterId);
inRegsCur.emplace_back(it->second.registerId);
}
}
}
@ -170,6 +178,7 @@ int TraversalBlock::initialize() {
void TraversalBlock::executeExpressions() {
DEBUG_BEGIN_BLOCK();
AqlItemBlock* cur = _buffer.front();
size_t index = 0;
for (auto& map : *_expressions) {
for (size_t i = 0; i < map.second.size(); ++i) {
// Right now no inVars are allowed.
@ -178,8 +187,8 @@ void TraversalBlock::executeExpressions() {
if (it != nullptr && it->expression != nullptr) {
// inVars and inRegs needs fixx
bool mustDestroy;
AqlValue a = it->expression->execute(_trx, cur, _pos, _inVars[i],
_inRegs[i], mustDestroy);
AqlValue a = it->expression->execute(_trx, cur, _pos, _inVars[index],
_inRegs[index], mustDestroy);
AqlValueGuard guard(a, mustDestroy);
@ -196,6 +205,7 @@ void TraversalBlock::executeExpressions() {
it->compareTo.reset(builder);
}
++index;
}
}
throwIfKilled(); // check if we were aborted

View File

@ -702,11 +702,10 @@ void TraversalNode::setCondition(arangodb::aql::Condition* condition) {
Ast::getReferencedVariables(condition->root(), varsUsedByCondition);
for (auto const& oneVar : varsUsedByCondition) {
if ((_vertexOutVariable != nullptr &&
oneVar->id != _vertexOutVariable->id) &&
(_edgeOutVariable != nullptr && oneVar->id != _edgeOutVariable->id) &&
(_pathOutVariable != nullptr && oneVar->id != _pathOutVariable->id) &&
(_inVariable != nullptr && oneVar->id != _inVariable->id)) {
if ((_vertexOutVariable == nullptr || oneVar->id != _vertexOutVariable->id) &&
(_edgeOutVariable == nullptr || oneVar->id != _edgeOutVariable->id) &&
(_pathOutVariable == nullptr || oneVar->id != _pathOutVariable->id) &&
(_inVariable == nullptr || oneVar->id != _inVariable->id)) {
_conditionVariables.emplace_back(oneVar);
}
}

View File

@ -256,7 +256,56 @@ function optimizerRuleTestSuite () {
assertNotEqual(-1, result.plan.rules.indexOf(ruleName), query);
assertEqual(simplePlan[2].type, "NoResultsNode");
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test multiple conditions
////////////////////////////////////////////////////////////////////////////////
testCondVars1 : function () {
var queries = [
"LET data = (FOR i IN 1..1 RETURN i) FOR v, e, p IN 1..10 OUTBOUND data GRAPH '" + graphName + "' FILTER p.vertices[0]._id == '123' FILTER p.vertices[1]._id != null FILTER p.edges[0]._id IN data[*].foo.bar RETURN 1"
];
queries.forEach(function(query) {
var result = AQL_EXPLAIN(query);
assertNotEqual(-1, result.plan.rules.indexOf(ruleName), query);
assertEqual(0, AQL_EXECUTE(query).json.length);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test multiple conditions
////////////////////////////////////////////////////////////////////////////////
testCondVars2 : function () {
var queries = [
"LET data = (FOR i IN 1..1 RETURN i) FOR v, e, p IN 1..10 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.vertices[0]._id == '123' FILTER p.vertices[1]._id != null FILTER p.edges[0]._id IN data[*].foo.bar RETURN 1"
];
queries.forEach(function(query) {
var result = AQL_EXPLAIN(query);
assertNotEqual(-1, result.plan.rules.indexOf(ruleName), query);
assertEqual(0, AQL_EXECUTE(query).json.length);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test multiple conditions
////////////////////////////////////////////////////////////////////////////////
testCondVars3 : function () {
var queries = [
"LET data = (FOR i IN 1..1 RETURN i) FOR v, e, p IN 1..10 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.vertices[0]._id == '123' FILTER p.vertices[1]._id != null FILTER p.edges[0]._id IN data[*].foo.bar FILTER p.edges[1]._key IN data[*].bar.baz._id RETURN 1"
];
queries.forEach(function(query) {
var result = AQL_EXPLAIN(query);
assertNotEqual(-1, result.plan.rules.indexOf(ruleName), query);
assertEqual(0, AQL_EXECUTE(query).json.length);
});
}
};
}