mirror of https://gitee.com/bigwinds/arangodb
Jan's patch
This commit is contained in:
parent
901c65559c
commit
b301102655
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue