1
0
Fork 0

use Ast::ReverseOperator

This commit is contained in:
Jan Steemann 2014-11-08 22:31:31 +01:00
parent 738636db2d
commit 9c5d150866
8 changed files with 96 additions and 71 deletions

View File

@ -81,7 +81,7 @@ AstNode const Ast::EmptyStringNode{ "", VALUE_TYPE_STRING };
/// @brief inverse comparison operators
////////////////////////////////////////////////////////////////////////////////
std::unordered_map<int, AstNodeType> const Ast::ReverseOperators{
std::unordered_map<int, AstNodeType> const Ast::NegatedOperators{
{ static_cast<int>(NODE_TYPE_OPERATOR_BINARY_EQ), NODE_TYPE_OPERATOR_BINARY_NE },
{ static_cast<int>(NODE_TYPE_OPERATOR_BINARY_NE), NODE_TYPE_OPERATOR_BINARY_EQ },
{ static_cast<int>(NODE_TYPE_OPERATOR_BINARY_GT), NODE_TYPE_OPERATOR_BINARY_LE },
@ -92,6 +92,18 @@ std::unordered_map<int, AstNodeType> const Ast::ReverseOperators{
{ static_cast<int>(NODE_TYPE_OPERATOR_BINARY_NIN), NODE_TYPE_OPERATOR_BINARY_IN }
};
////////////////////////////////////////////////////////////////////////////////
/// @brief reverse comparison operators
////////////////////////////////////////////////////////////////////////////////
std::unordered_map<int, AstNodeType> const Ast::ReversedOperators{
{ static_cast<int>(NODE_TYPE_OPERATOR_BINARY_EQ), NODE_TYPE_OPERATOR_BINARY_EQ },
{ static_cast<int>(NODE_TYPE_OPERATOR_BINARY_GT), NODE_TYPE_OPERATOR_BINARY_LT },
{ static_cast<int>(NODE_TYPE_OPERATOR_BINARY_GE), NODE_TYPE_OPERATOR_BINARY_LE },
{ static_cast<int>(NODE_TYPE_OPERATOR_BINARY_LT), NODE_TYPE_OPERATOR_BINARY_GT },
{ static_cast<int>(NODE_TYPE_OPERATOR_BINARY_LE), NODE_TYPE_OPERATOR_BINARY_GE }
};
// -----------------------------------------------------------------------------
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
@ -1083,6 +1095,19 @@ AstNode* Ast::clone (AstNode const* node) {
return copy;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the reversed operator for a comparison operator
////////////////////////////////////////////////////////////////////////////////
AstNodeType Ast::ReverseOperator (AstNodeType type) {
auto it = ReversedOperators.find(static_cast<int>(type));
if (it == ReversedOperators.end()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid node type for inversed operator");
}
return (*it).second;
}
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
@ -1222,8 +1247,8 @@ AstNode* Ast::optimizeNotExpression (AstNode* node) {
auto lhs = operand->getMember(0);
auto rhs = operand->getMember(1);
auto it = ReverseOperators.find(static_cast<int>(operand->type));
TRI_ASSERT(it != ReverseOperators.end());
auto it = NegatedOperators.find(static_cast<int>(operand->type));
TRI_ASSERT(it != NegatedOperators.end());
return createNodeBinaryOperator((*it).second, lhs, rhs);
}

View File

@ -489,6 +489,12 @@ namespace triagens {
AstNode* clone (AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief get the reversed operator for a comparison operator
////////////////////////////////////////////////////////////////////////////////
static AstNodeType ReverseOperator (AstNodeType);
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
@ -624,11 +630,16 @@ namespace triagens {
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief inverse comparison operators
/// @brief negated comparison operators
////////////////////////////////////////////////////////////////////////////////
static std::unordered_map<int, AstNodeType> const ReverseOperators;
static std::unordered_map<int, AstNodeType> const NegatedOperators;
////////////////////////////////////////////////////////////////////////////////
/// @brief reverse comparison operators
////////////////////////////////////////////////////////////////////////////////
static std::unordered_map<int, AstNodeType> const ReversedOperators;
// -----------------------------------------------------------------------------
// --SECTION-- private variables

View File

@ -452,15 +452,15 @@ void Optimizer::setupRules () {
//////////////////////////////////////////////////////////////////////////////
// try to replace simple OR conditions with IN
registerRule("replace-OR-with-IN",
registerRule("replace-or-with-in",
replaceOrWithIn,
replaceOrWithIn_pass6,
true);
// try to remove redundant OR
registerRule("remove-redundant-OR",
removeRedundantOR,
removeRedundantOR_pass6,
// try to remove redundant OR conditions
registerRule("remove-redundant-or",
removeRedundantOr,
removeRedundantOr_pass6,
true);
// try to find a filter after an enumerate collection and find an index . . .
@ -474,10 +474,10 @@ void Optimizer::setupRules () {
useIndexForSort,
useIndexForSort_pass6,
true);
#if 0
#if 0
// try to remove filters which are covered by index ranges
// rule seems to work, but tests are still missing
// TODO: rule seems to work, but tests are still missing
registerRule("remove-filter-covered-by-index",
removeFiltersCoveredByIndex,
removeFiltersCoveredByIndex_pass6,

View File

@ -131,7 +131,7 @@ namespace triagens {
replaceOrWithIn_pass6 = 810,
// remove redundant OR conditions
removeRedundantOR_pass6 = 820,
removeRedundantOr_pass6 = 820,
// try to find a filter after an enumerate collection and find an index . . .
useIndexRange_pass6 = 830,

View File

@ -1477,9 +1477,7 @@ int triagens::aql::useIndexForSort (Optimizer* opt,
return TRI_ERROR_NO_ERROR;
}
#if 0
// TODO: finish rule and test it
struct FilterCondition {
std::string variableName;
std::string attributeName;
@ -1561,19 +1559,17 @@ struct FilterCondition {
lhs = node->getMember(1);
rhs = node->getMember(0);
auto it = Ast::ReverseOperators.find(static_cast<int>(node->type));
TRI_ASSERT(it != Ast::ReverseOperators.end());
op = (*it).second;
op = Ast::ReverseOperator(node->type);
}
if (found) {
TRI_ASSERT(lhs->type == NODE_TYPE_VALUE);
TRI_ASSERT(rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS);
std::function<void(AstNode const*)> buildName = [&] (AstNode const* node) -> void {
std::function<void(AstNode const*, std::string&, std::string&)> buildName =
[&] (AstNode const* node, std::string& variableName, std::string& attributeName) -> void {
if (node->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
buildName(node->getMember(0));
buildName(node->getMember(0), variableName, attributeName);
if (! attributeName.empty()) {
attributeName.push_back('.');
@ -1588,7 +1584,9 @@ struct FilterCondition {
};
if (attributeName.empty()) {
buildName(rhs);
TRI_ASSERT(! variableName.empty());
buildName(rhs, variableName, attributeName);
if (op == NODE_TYPE_OPERATOR_BINARY_EQ ||
op == NODE_TYPE_OPERATOR_BINARY_NE) {
lowInclusive = true;
@ -1615,10 +1613,19 @@ struct FilterCondition {
return true;
}
// else if (attributeName == std::string(buffer.c_str(), buffer.length())) {
// same attribute
// TODO
// }
else {
// already have collected something, now check if the next condition
// is for the same variable / attribute
std::string compareVariableName;
std::string compareAttributeName;
buildName(rhs, compareVariableName, compareAttributeName);
if (variableName == compareVariableName &&
attributeName == compareAttributeName) {
// same attribute
// TODO
}
}
// fall-through
}
@ -1638,7 +1645,6 @@ struct FilterCondition {
};
////////////////////////////////////////////////////////////////////////////////
/// @brief try to remove filters which are covered by indexes
////////////////////////////////////////////////////////////////////////////////
@ -1657,7 +1663,9 @@ int triagens::aql::removeFiltersCoveredByIndex (Optimizer* opt,
// auto outVar = cn->getVariablesSetHere();
auto setter = plan->getVarSetBy(inVar[0]->id);
TRI_ASSERT(setter != nullptr);
if (setter == nullptr) {
continue;
}
if (setter->getType() != EN::CALCULATION) {
continue;
@ -1717,7 +1725,6 @@ int triagens::aql::removeFiltersCoveredByIndex (Optimizer* opt,
return TRI_ERROR_NO_ERROR;
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief helper to compute lots of permutation tuples
@ -2761,8 +2768,7 @@ int triagens::aql::replaceOrWithIn (Optimizer* opt,
LEAVE_BLOCK;
}
struct RemoveRedundantOR {
struct RemoveRedundantOr {
AstNode const* bestValue = nullptr;
AstNodeType comparison;
bool inclusive;
@ -2791,19 +2797,22 @@ struct RemoveRedundantOR {
(type == NODE_TYPE_OPERATOR_BINARY_GE
|| type == NODE_TYPE_OPERATOR_BINARY_GT)) {
return -1; //high bound
} else if ((comparison == NODE_TYPE_OPERATOR_BINARY_GE
}
else if ((comparison == NODE_TYPE_OPERATOR_BINARY_GE
|| comparison == NODE_TYPE_OPERATOR_BINARY_GT) &&
(type == NODE_TYPE_OPERATOR_BINARY_LE
|| type == NODE_TYPE_OPERATOR_BINARY_LT)) {
return 1; //low bound
}
} else {
}
else {
if ((comparison == NODE_TYPE_OPERATOR_BINARY_LE
|| comparison == NODE_TYPE_OPERATOR_BINARY_LT) &&
(type == NODE_TYPE_OPERATOR_BINARY_LE
|| type == NODE_TYPE_OPERATOR_BINARY_LT)) {
return -1; //high bound
} else if ((comparison == NODE_TYPE_OPERATOR_BINARY_GE
}
else if ((comparison == NODE_TYPE_OPERATOR_BINARY_GE
|| comparison == NODE_TYPE_OPERATOR_BINARY_GT) &&
(type == NODE_TYPE_OPERATOR_BINARY_GE
|| type == NODE_TYPE_OPERATOR_BINARY_GT)) {
@ -2823,25 +2832,10 @@ struct RemoveRedundantOR {
return (isInclusiveBound(type) ? true : false);
}
return (cmp * lowhigh == 1);
};
AstNodeType reverseComparison (AstNodeType type) {
if (type == NODE_TYPE_OPERATOR_BINARY_LE) {
return NODE_TYPE_OPERATOR_BINARY_GE;
}
else if (type == NODE_TYPE_OPERATOR_BINARY_LT) {
return NODE_TYPE_OPERATOR_BINARY_GT;
}
else if (type == NODE_TYPE_OPERATOR_BINARY_GT) {
return NODE_TYPE_OPERATOR_BINARY_LT;
}
else {
return NODE_TYPE_OPERATOR_BINARY_LE;
}
}
bool hasRedundantCondition (AstNode const* node) {
if(finder.find(node, NODE_TYPE_OPERATOR_BINARY_LT, commonNode, commonName)){
if (finder.find(node, NODE_TYPE_OPERATOR_BINARY_LT, commonNode, commonName)) {
return hasRedundantConditionWalker(node);
}
return false;
@ -2855,10 +2849,10 @@ struct RemoveRedundantOR {
hasRedundantConditionWalker(node->getMember(1)));
}
if( type == NODE_TYPE_OPERATOR_BINARY_LE
if (type == NODE_TYPE_OPERATOR_BINARY_LE
|| type == NODE_TYPE_OPERATOR_BINARY_LT
|| type == NODE_TYPE_OPERATOR_BINARY_GE
|| type == NODE_TYPE_OPERATOR_BINARY_GT ) {
|| type == NODE_TYPE_OPERATOR_BINARY_GT) {
auto lhs = node->getMember(0);
auto rhs = node->getMember(1);
@ -2867,8 +2861,8 @@ struct RemoveRedundantOR {
&& ! hasRedundantConditionWalker(lhs)
&& lhs->isConstant()) {
if (!isComparisonSet) {
comparison = reverseComparison(type);
if (! isComparisonSet) {
comparison = Ast::ReverseOperator(type);
bestValue = lhs;
isComparisonSet = true;
return true;
@ -2880,7 +2874,7 @@ struct RemoveRedundantOR {
}
if (compareBounds(type, lhs, lowhigh)) {
comparison = reverseComparison(type);
comparison = Ast::ReverseOperator(type);
bestValue = lhs;
}
return true;
@ -2888,7 +2882,7 @@ struct RemoveRedundantOR {
if (hasRedundantConditionWalker(lhs)
&& ! hasRedundantConditionWalker(rhs)
&& rhs->isConstant()) {
if (!isComparisonSet) {
if (! isComparisonSet) {
comparison = type;
bestValue = rhs;
isComparisonSet = true;
@ -2915,7 +2909,8 @@ struct RemoveRedundantOR {
type == NODE_TYPE_INDEXED_ACCESS) {
// get a string representation of the node for comparisons
return (node->toString() == commonName);
} else if (node->isBoolValue()) {
}
else if (node->isBoolValue()) {
return true;
}
@ -2923,7 +2918,7 @@ struct RemoveRedundantOR {
}
};
int triagens::aql::removeRedundantOR (Optimizer* opt,
int triagens::aql::removeRedundantOr (Optimizer* opt,
ExecutionPlan* plan,
Optimizer::Rule const* rule) {
ENTER_BLOCK;
@ -2951,19 +2946,13 @@ int triagens::aql::removeRedundantOR (Optimizer* opt,
continue;
}
RemoveRedundantOR remover;
if(remover.hasRedundantCondition(cn->expression()->node())){
RemoveRedundantOr remover;
if (remover.hasRedundantCondition(cn->expression()->node())) {
Expression* expr = nullptr;
ExecutionNode* newNode = nullptr;
auto astNode = remover.createReplacementNode(plan->getAst());
try {
expr = new Expression(plan->getAst(), astNode);
}
catch (...) {
delete astNode;
throw;
}
expr = new Expression(plan->getAst(), astNode);
try {
newNode = new CalculationNode(plan, plan->nextId(), expr, outVar[0]);

View File

@ -182,7 +182,7 @@ namespace triagens {
int replaceOrWithIn (Optimizer*, ExecutionPlan*, Optimizer::Rule const*);
int removeRedundantOR (Optimizer*, ExecutionPlan*, Optimizer::Rule const*);
int removeRedundantOr (Optimizer*, ExecutionPlan*, Optimizer::Rule const*);
} // namespace aql
} // namespace triagens

View File

@ -38,7 +38,7 @@ var getQueryResults = helper.getQueryResults;
////////////////////////////////////////////////////////////////////////////////
function NewAqlRemoveRedundantORTestSuite () {
var ruleName = "remove-redundant-OR";
var ruleName = "remove-redundant-or";
var isRuleUsed = function (query, params) {
var result = AQL_EXPLAIN(query, params, { optimizer: { rules: [ "-all", "+" + ruleName ] } });

View File

@ -39,7 +39,7 @@ var getQueryResults = helper.getQueryResults;
function NewAqlReplaceORWithINTestSuite () {
var replace;
var ruleName = "replace-OR-with-IN";
var ruleName = "replace-or-with-in";
var isRuleUsed = function (query, params) {
var result = AQL_EXPLAIN(query, params, { optimizer: { rules: [ "-all", "+" + ruleName ] } });