mirror of https://gitee.com/bigwinds/arangodb
nearly working better version of previous
This commit is contained in:
parent
e51071525b
commit
04770d3563
|
@ -2270,11 +2270,34 @@ int triagens::aql::undistributeRemoveAfterEnumColl (Optimizer* opt,
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct OrToInConverter {
|
struct OrToInConverter {
|
||||||
AstNode const* variableNode;
|
AstNode const* variableNode = nullptr;
|
||||||
|
//const char* variableName;
|
||||||
std::vector<AstNode const*> valueNodes;
|
std::vector<AstNode const*> valueNodes;
|
||||||
std::vector<std::string> possibleNames;
|
|
||||||
std::vector<AstNode const*> possibleNodes;
|
std::vector<AstNode const*> possibleNodes;
|
||||||
std::string variableName;
|
std::vector<AstNode const*> orConditions;
|
||||||
|
|
||||||
|
std::string getString (AstNode const* node) {
|
||||||
|
triagens::basics::StringBuffer buffer(TRI_UNKNOWN_MEM_ZONE);
|
||||||
|
node->append(&buffer, false);
|
||||||
|
return std::string(buffer.c_str(), buffer.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compareNodes (AstNode const* lhs, AstNode const* rhs) {
|
||||||
|
if (lhs->numMembers() == rhs->numMembers()) {
|
||||||
|
if (lhs->numMembers() == 1) {
|
||||||
|
return (getString(lhs) == getString(rhs));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (size_t i = 0; i < lhs->numMembers(); i++) {
|
||||||
|
if (! compareNodes(lhs->getMember(i), rhs->getMember(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
AstNode* buildInExpression (Ast* ast) {
|
AstNode* buildInExpression (Ast* ast) {
|
||||||
// the list of comparison values
|
// the list of comparison values
|
||||||
|
@ -2289,6 +2312,100 @@ struct OrToInConverter {
|
||||||
list);
|
list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool flattenOr (AstNode const* node) {
|
||||||
|
if (node->type == NODE_TYPE_OPERATOR_BINARY_OR) {
|
||||||
|
return (flattenOr(node->getMember(0)) && flattenOr(node->getMember(1)));
|
||||||
|
}
|
||||||
|
if (node->type == NODE_TYPE_OPERATOR_BINARY_EQ) {
|
||||||
|
orConditions.push_back(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool findNameAndNode (AstNode const* node) {
|
||||||
|
|
||||||
|
if (! flattenOr(node)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TRI_ASSERT(orConditions.size() > 1);
|
||||||
|
|
||||||
|
for (AstNode const* n: orConditions) {
|
||||||
|
|
||||||
|
auto lhs = n->getMember(0);
|
||||||
|
auto rhs = n->getMember(1);
|
||||||
|
|
||||||
|
if (variableNode != nullptr) {
|
||||||
|
return (compareNodes(lhs, variableNode)
|
||||||
|
|| compareNodes(rhs, variableNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs->type == NODE_TYPE_VALUE
|
||||||
|
&& (rhs->type == NODE_TYPE_REFERENCE
|
||||||
|
|| rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS
|
||||||
|
|| rhs->type == NODE_TYPE_INDEXED_ACCESS)) {
|
||||||
|
variableNode = rhs;
|
||||||
|
//variableName = getString(rhs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rhs->type == NODE_TYPE_VALUE
|
||||||
|
&& (lhs->type == NODE_TYPE_REFERENCE
|
||||||
|
|| lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS
|
||||||
|
|| lhs->type == NODE_TYPE_INDEXED_ACCESS)) {
|
||||||
|
variableNode = lhs;
|
||||||
|
//variableName = getString(lhs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs->type == NODE_TYPE_REFERENCE) {
|
||||||
|
variableNode = lhs;
|
||||||
|
//variableName = getString(lhs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (rhs->type == NODE_TYPE_REFERENCE) {
|
||||||
|
variableNode = rhs;
|
||||||
|
//variableName = getString(rhs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS ||
|
||||||
|
lhs->type == NODE_TYPE_INDEXED_ACCESS) {
|
||||||
|
if (possibleNodes.size() == 2) {
|
||||||
|
for (size_t i = 0; i < 2; i++) {
|
||||||
|
if (compareNodes(lhs, possibleNodes[i])) {
|
||||||
|
variableNode = possibleNodes[i];
|
||||||
|
//variableName = getString(possibleNodes[i]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
possibleNodes.push_back(lhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS ||
|
||||||
|
rhs->type == NODE_TYPE_INDEXED_ACCESS) {
|
||||||
|
if (possibleNodes.size() == 2) {
|
||||||
|
for (size_t i = 0; i < 2; i++) {
|
||||||
|
if (compareNodes(rhs, possibleNodes[i])) {
|
||||||
|
variableNode = possibleNodes[i];
|
||||||
|
//variableName = getString(possibleNodes[i]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
possibleNodes.push_back(rhs);
|
||||||
|
//continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool canConvertExpression (AstNode const* node) {
|
bool canConvertExpression (AstNode const* node) {
|
||||||
if (node->type == NODE_TYPE_OPERATOR_BINARY_OR) {
|
if (node->type == NODE_TYPE_OPERATOR_BINARY_OR) {
|
||||||
return (canConvertExpression(node->getMember(0)) &&
|
return (canConvertExpression(node->getMember(0)) &&
|
||||||
|
@ -2309,65 +2426,16 @@ struct OrToInConverter {
|
||||||
valueNodes.push_back(rhs);
|
valueNodes.push_back(rhs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS
|
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS && canConvertExpression(rhs)) {
|
||||||
&& lhs->getMember(0)->isArray() && canConvertExpression(rhs)) {
|
|
||||||
// value == attr
|
// value == attr
|
||||||
valueNodes.push_back(lhs);
|
valueNodes.push_back(lhs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS
|
if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS && canConvertExpression(lhs)) {
|
||||||
&& rhs->getMember(0)->isArray() && canConvertExpression(lhs)) {
|
|
||||||
// value == attr
|
// value == attr
|
||||||
valueNodes.push_back(rhs);
|
valueNodes.push_back(rhs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// for things like "FOR a IN docs a.x == a.y || a.z == 1 RETURN a"
|
|
||||||
if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS
|
|
||||||
&& lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
|
||||||
if (variableName.empty()) {
|
|
||||||
triagens::basics::StringBuffer buffer(TRI_UNKNOWN_MEM_ZONE);
|
|
||||||
lhs->append(&buffer, false);
|
|
||||||
auto lhsName = std::string(buffer.c_str(), buffer.length());
|
|
||||||
|
|
||||||
triagens::basics::StringBuffer buffer1(TRI_UNKNOWN_MEM_ZONE);
|
|
||||||
rhs->append(&buffer1, false);
|
|
||||||
auto rhsName = std::string(buffer1.c_str(), buffer1.length());
|
|
||||||
|
|
||||||
if (! possibleNames.empty()) {
|
|
||||||
if (lhsName == possibleNames[0] || rhsName == possibleNames[0]) {
|
|
||||||
variableName = possibleNames[0];
|
|
||||||
variableNode = possibleNodes[0];
|
|
||||||
}
|
|
||||||
else if (lhsName == possibleNames[1] || rhsName == possibleNames[1]) {
|
|
||||||
variableName = possibleNames[1];
|
|
||||||
variableNode = possibleNodes[1];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
possibleNames.clear();
|
|
||||||
possibleNodes.clear();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
possibleNames.push_back(lhsName);
|
|
||||||
possibleNames.push_back(rhsName);
|
|
||||||
possibleNodes.push_back(lhs);
|
|
||||||
possibleNodes.push_back(rhs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (! variableName.empty()) {
|
|
||||||
if (canConvertExpression(rhs)) {
|
|
||||||
valueNodes.push_back(lhs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (canConvertExpression(lhs)) {
|
|
||||||
valueNodes.push_back(rhs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lhs->type == NODE_TYPE_INDEXED_ACCESS && canConvertExpression(rhs)) {
|
if (lhs->type == NODE_TYPE_INDEXED_ACCESS && canConvertExpression(rhs)) {
|
||||||
// attr == value
|
// attr == value
|
||||||
valueNodes.push_back(lhs);
|
valueNodes.push_back(lhs);
|
||||||
|
@ -2380,29 +2448,13 @@ struct OrToInConverter {
|
||||||
}
|
}
|
||||||
// fall-through intentional
|
// fall-through intentional
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (node->type == NODE_TYPE_REFERENCE ||
|
else if (node->type == NODE_TYPE_REFERENCE ||
|
||||||
node->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
node->type == NODE_TYPE_ATTRIBUTE_ACCESS ||
|
||||||
|
node->type == NODE_TYPE_INDEXED_ACCESS) {
|
||||||
// get a string representation of the node for comparisons
|
// get a string representation of the node for comparisons
|
||||||
triagens::basics::StringBuffer buffer(TRI_UNKNOWN_MEM_ZONE);
|
std::string nodeString = getString(node);
|
||||||
node->append(&buffer, false);
|
return nodeString == getString(variableNode);
|
||||||
|
|
||||||
if (variableName.empty()) {
|
|
||||||
TRI_ASSERT(valueNodes.empty());
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fall-through intentional
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2433,7 +2485,8 @@ int triagens::aql::replaceORwithIN (Optimizer* opt,
|
||||||
}
|
}
|
||||||
|
|
||||||
OrToInConverter converter;
|
OrToInConverter converter;
|
||||||
if (converter.canConvertExpression(cn->expression()->node())) {
|
if (converter.findNameAndNode(cn->expression()->node())
|
||||||
|
&& converter.canConvertExpression(cn->expression()->node())) {
|
||||||
Expression* expr = nullptr;
|
Expression* expr = nullptr;
|
||||||
ExecutionNode* newNode = nullptr;
|
ExecutionNode* newNode = nullptr;
|
||||||
auto inNode = converter.buildInExpression(plan->getAst());
|
auto inNode = converter.buildInExpression(plan->getAst());
|
||||||
|
|
Loading…
Reference in New Issue