From 992ac23450c390a70c533ce6de86d9957f08344b Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 16 Sep 2014 15:48:33 +0200 Subject: [PATCH] fixed ranges --- arangod/Aql/OptimizerRules.cpp | 37 ++++++++++++------- arangod/Aql/RangeInfo.cpp | 16 ++++---- arangod/Aql/RangeInfo.h | 6 ++- .../aql-optimizer-rule-use-index-for-sort.js | 2 +- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/arangod/Aql/OptimizerRules.cpp b/arangod/Aql/OptimizerRules.cpp index 85bb18ea50..9e186ad201 100644 --- a/arangod/Aql/OptimizerRules.cpp +++ b/arangod/Aql/OptimizerRules.cpp @@ -985,7 +985,9 @@ class FilterToEnumCollFinder : public WalkerWorker { return false; } - void buildRangeInfo (AstNode const* node, std::string& enumCollVar, std::string& attr) { + void buildRangeInfo (AstNode const* node, + std::string& enumCollVar, + std::string& attr) { if (node->type == NODE_TYPE_REFERENCE) { auto x = static_cast(node->getData()); auto setter = _plan->getVarSetBy(x->id); @@ -997,9 +999,10 @@ class FilterToEnumCollFinder : public WalkerWorker { } if (node->type == NODE_TYPE_ATTRIBUTE_ACCESS) { - char const* attributeName = node->getStringValue(); buildRangeInfo(node->getMember(0), enumCollVar, attr); + if (! enumCollVar.empty()) { + char const* attributeName = node->getStringValue(); attr.append(attributeName); attr.push_back('.'); } @@ -1015,24 +1018,22 @@ class FilterToEnumCollFinder : public WalkerWorker { // Found a multiple attribute access of a variable _ranges->insert(enumCollVar, attr.substr(0, attr.size() - 1), RangeInfoBound(lhs, true), RangeInfoBound(lhs, true), true); + + enumCollVar.clear(); + attr.clear(); } } - enumCollVar.clear(); - attr.clear(); - if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) { buildRangeInfo(lhs, enumCollVar, attr); if (! enumCollVar.empty()) { // Found a multiple attribute access of a variable _ranges->insert(enumCollVar, attr.substr(0, attr.size() - 1), RangeInfoBound(rhs, true), RangeInfoBound(rhs, true), true); + enumCollVar.clear(); + attr.clear(); } } - - enumCollVar.clear(); - attr.clear(); - return; } @@ -1046,8 +1047,6 @@ class FilterToEnumCollFinder : public WalkerWorker { auto lhs = node->getMember(0); auto rhs = node->getMember(1); - RangeInfoBound low; - RangeInfoBound high; if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) { // Attribute access on the right: @@ -1055,6 +1054,9 @@ class FilterToEnumCollFinder : public WalkerWorker { // of a variable on the right: buildRangeInfo(rhs, enumCollVar, attr); if (! enumCollVar.empty()) { + RangeInfoBound low; + RangeInfoBound high; + // Constant value on the left, so insert a constant condition: if (node->type == NODE_TYPE_OPERATOR_BINARY_GE || node->type == NODE_TYPE_OPERATOR_BINARY_GT) { @@ -1065,9 +1067,10 @@ class FilterToEnumCollFinder : public WalkerWorker { } _ranges->insert(enumCollVar, attr.substr(0, attr.size() - 1), low, high, false); + + enumCollVar.clear(); + attr.clear(); } - enumCollVar.clear(); - attr.clear(); } if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) { @@ -1076,6 +1079,9 @@ class FilterToEnumCollFinder : public WalkerWorker { // of a variable on the left: buildRangeInfo(lhs, enumCollVar, attr); if (! enumCollVar.empty()) { + RangeInfoBound low; + RangeInfoBound high; + // Constant value on the right, so insert a constant condition: if (node->type == NODE_TYPE_OPERATOR_BINARY_GE || node->type == NODE_TYPE_OPERATOR_BINARY_GT) { @@ -1086,6 +1092,9 @@ class FilterToEnumCollFinder : public WalkerWorker { } _ranges->insert(enumCollVar, attr.substr(0, attr.size() - 1), low, high, false); + + enumCollVar.clear(); + attr.clear(); } } @@ -1102,9 +1111,9 @@ class FilterToEnumCollFinder : public WalkerWorker { buildRangeInfo(node->getMember(1), enumCollVar, attr); } */ + // default case attr = ""; enumCollVar = ""; - return; } }; diff --git a/arangod/Aql/RangeInfo.cpp b/arangod/Aql/RangeInfo.cpp index 06711048ad..dd606b00be 100644 --- a/arangod/Aql/RangeInfo.cpp +++ b/arangod/Aql/RangeInfo.cpp @@ -113,7 +113,7 @@ void RangeInfoBound::andCombineUpperBounds (RangeInfoBound const& that) { /// (if needed) nodes are registered with the ast //////////////////////////////////////////////////////////////////////////////// -AstNode const* RangeInfoBound::getExpressionAst(Ast* ast) const { +AstNode const* RangeInfoBound::getExpressionAst (Ast* ast) const { if (_expressionAst != nullptr) { return _expressionAst; } @@ -195,7 +195,6 @@ triagens::basics::Json RangeInfo::toJson() const { //////////////////////////////////////////////////////////////////////////////// void RangesInfo::insert (RangeInfo newRange) { - TRI_ASSERT(newRange.isDefined()); std::unordered_map* oldMap = find(newRange._var); @@ -224,10 +223,9 @@ void RangesInfo::insert (RangeInfo newRange) { //////////////////////////////////////////////////////////////////////////////// void RangeInfo::fuse (RangeInfo const& that) { - TRI_ASSERT(_var == that._var); TRI_ASSERT(_attr == that._attr); - + if (! isValid()) { // intersection of the empty set with any set is empty! return; @@ -281,16 +279,18 @@ void RangeInfo::fuse (RangeInfo const& that) { } } } -}; +} //////////////////////////////////////////////////////////////////////////////// /// @brief insert if there is no range corresponding to variable name , /// and attribute , and otherwise intersection with existing range //////////////////////////////////////////////////////////////////////////////// -void RangesInfo::insert (std::string var, std::string name, - RangeInfoBound low, RangeInfoBound high, +void RangesInfo::insert (std::string const& var, + std::string const& name, + RangeInfoBound low, + RangeInfoBound high, bool equality) { insert(RangeInfo(var, name, low, high, equality)); -}; +} diff --git a/arangod/Aql/RangeInfo.h b/arangod/Aql/RangeInfo.h index 88d94664f1..a00971e530 100644 --- a/arangod/Aql/RangeInfo.h +++ b/arangod/Aql/RangeInfo.h @@ -575,8 +575,10 @@ namespace triagens { /// bounds are variable and can only be computed at runtime. //////////////////////////////////////////////////////////////////////////////// - void insert (std::string var, std::string name, - RangeInfoBound low, RangeInfoBound high, + void insert (std::string const& var, + std::string const& name, + RangeInfoBound low, + RangeInfoBound high, bool equality); //////////////////////////////////////////////////////////////////////////////// diff --git a/js/server/tests/aql-optimizer-rule-use-index-for-sort.js b/js/server/tests/aql-optimizer-rule-use-index-for-sort.js index d81cd1d897..a0cad92cfa 100644 --- a/js/server/tests/aql-optimizer-rule-use-index-for-sort.js +++ b/js/server/tests/aql-optimizer-rule-use-index-for-sort.js @@ -771,7 +771,7 @@ function optimizerRuleTestSuite() { // The IndexRangeNode created by this rule should be more clever, it knows the ranges. var RAs = getRangeAttributes(XPresult); var first = getRangeAttribute(RAs[0], "v", "a", 1); - + assertEqual(first.highs.length, 0, "no variable high bounds"); assertEqual(first.lows.length, 0, "no variable low bounds"); assertEqual(first.lowConst.bound, 4, "proper value was set");