1
0
Fork 0

Jan's patch

This commit is contained in:
James 2014-11-03 09:32:12 +00:00
parent 901c65559c
commit b301102655
1 changed files with 81 additions and 78 deletions

View File

@ -2269,86 +2269,73 @@ int triagens::aql::undistributeRemoveAfterEnumColl (Optimizer* opt,
/// @brief /// @brief
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// recursively check the expression in the calculation node, to make sure it is struct OrToInConverter {
// an OR of equality comparisons over the same variable and attribute. AstNode const* variableNode;
std::vector<AstNode const*> valueNodes;
std::string variableName;
bool buildExpression (AstNode const* node, AstNode* buildInExpression (Ast* ast) {
AstNode*& expr, // the list of comparison values
ExecutionPlan* plan) { auto list = ast->createNodeList();
for (auto x : valueNodes) {
list->addMember(x);
}
if (node->type == NODE_TYPE_REFERENCE) { // return a new IN operator node
if (expr->numMembers() == 0) { return ast->createNodeBinaryOperator(NODE_TYPE_OPERATOR_BINARY_IN,
return true; variableNode->clone(ast),
} list);
auto thisVar = static_cast<Variable*>(node->getData());
auto existingVar =
static_cast<Variable*>(expr->getMember(0)->getMember(0)->getData());
if (thisVar->id == existingVar->id) {
return true;
}
return false;
} }
if (node->type == NODE_TYPE_ATTRIBUTE_ACCESS) { bool canConvertExpression (AstNode const* node) {
if(buildExpression(node->getMember(0), expr, plan)) { if (node->type == NODE_TYPE_OPERATOR_BINARY_OR) {
if (expr->numMembers() == 0) { return (canConvertExpression(node->getMember(0)) &&
expr->addMember(node->clone(plan->getAst())); canConvertExpression(node->getMember(1)));
}
if (node->type == NODE_TYPE_OPERATOR_BINARY_EQ) {
auto lhs = node->getMember(0);
auto rhs = node->getMember(1);
if (lhs->type == NODE_TYPE_VALUE && canConvertExpression(rhs)) {
// value == attr
valueNodes.push_back(lhs);
return true; return true;
} }
if (strcmp(node->getStringValue(), if (rhs->type == NODE_TYPE_VALUE && canConvertExpression(lhs)) {
expr->getMember(0)->getStringValue()) == 0) { // attr == value
valueNodes.push_back(rhs);
return true; return true;
} }
}
return false;
}
if (node->type == NODE_TYPE_OPERATOR_BINARY_EQ) { // fall-through intentional
auto lhs = node->getMember(0);
auto rhs = node->getMember(1);
if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
if(buildExpression(rhs, expr, plan)){
TRI_ASSERT(expr->numMembers() != 0);
if (lhs->type == NODE_TYPE_VALUE) {
if (expr->numMembers() == 1) {
expr->addMember(new AstNode(NODE_TYPE_LIST));
}
// keep the value in the lhs
expr->getMember(1)->addMember(lhs->clone(plan->getAst()));
return true;
}
}
return false;
} }
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) { else if (node->type == NODE_TYPE_REFERENCE ||
if(buildExpression(lhs, expr, plan)){ node->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
TRI_ASSERT(expr->numMembers() != 0); // get a string representation of the node for comparisons
if (rhs->type == NODE_TYPE_VALUE) { triagens::basics::StringBuffer buffer(TRI_UNKNOWN_MEM_ZONE);
if (expr->numMembers() == 1) { node->append(&buffer, false);
expr->addMember(new AstNode(NODE_TYPE_LIST));
}
// keep the value in the rhs
expr->getMember(1)->addMember(rhs->clone(plan->getAst()));
return true;
}
}
return false;
}
return false;
}
if (node->type == NODE_TYPE_OPERATOR_BINARY_OR) { if (variableName.empty()) {
if (buildExpression(node->getMember(0), expr, plan)) { TRI_ASSERT(valueNodes.empty());
if (buildExpression(node->getMember(1), expr, plan)) { // we don't have anything to compare with
// now store the node and its stringified version for future comparisons
variableNode = node;
variableName = std::string(buffer.c_str(), buffer.length());
return true;
}
else if (std::string(buffer.c_str(), buffer.length()) == variableName) {
// already have collected a variable. the other variable is identical
return true; return true;
} }
}
}
return false; // fall-through intentional
} }
return false;
}
};
int triagens::aql::replaceORwithIN (Optimizer* opt, int triagens::aql::replaceORwithIN (Optimizer* opt,
ExecutionPlan* plan, ExecutionPlan* plan,
@ -2371,16 +2358,32 @@ int triagens::aql::replaceORwithIN (Optimizer* opt,
if (outVar.size() != 1 || outVar[0]->id != inVar[0]->id) { if (outVar.size() != 1 || outVar[0]->id != inVar[0]->id) {
continue; continue;
} }
if (cn->expression()->node()->type != NODE_TYPE_OPERATOR_BINARY_OR) { if (cn->expression()->node()->type != NODE_TYPE_OPERATOR_BINARY_OR) {
continue; continue;
} }
AstNode* ast = new AstNode(NODE_TYPE_OPERATOR_BINARY_IN); OrToInConverter converter;
if (buildExpression(cn->expression()->node(), ast, plan)) { if (converter.canConvertExpression(cn->expression()->node())) {
auto expr = new Expression(plan->getAst(), const_cast<AstNode*>(ast)); Expression* expr = nullptr;
auto newNode = new CalculationNode(plan, plan->nextId(), expr, outVar[0]); ExecutionNode* newNode = nullptr;
auto inNode = converter.buildInExpression(plan->getAst());
try {
expr = new Expression(plan->getAst(), inNode);
}
catch (...) {
delete inNode;
throw;
}
try {
newNode = new CalculationNode(plan, plan->nextId(), expr, outVar[0]);
}
catch (...) {
delete expr;
throw;
}
//TODO clone outVar[0]?
plan->registerNode(newNode); plan->registerNode(newNode);
plan->replaceNode(cn, newNode); plan->replaceNode(cn, newNode);
modified = true; modified = true;