diff --git a/arangod/Aql/AstNode.cpp b/arangod/Aql/AstNode.cpp index e38e6f6586..95106986f7 100644 --- a/arangod/Aql/AstNode.cpp +++ b/arangod/Aql/AstNode.cpp @@ -238,7 +238,8 @@ static TRI_json_type_e GetNodeCompareType (AstNode const* node) { //////////////////////////////////////////////////////////////////////////////// int triagens::aql::CompareAstNodes (AstNode const* lhs, - AstNode const* rhs) { + AstNode const* rhs, + bool compareUtf8) { if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) { lhs = ResolveAttribute(lhs); } @@ -251,6 +252,7 @@ int triagens::aql::CompareAstNodes (AstNode const* lhs, if (lType != rType) { int diff = static_cast(lType) - static_cast(rType); + TRI_ASSERT_EXPENSIVE(diff != 0); if (diff < 0) { @@ -268,6 +270,7 @@ int triagens::aql::CompareAstNodes (AstNode const* lhs, } else if (lType == TRI_JSON_BOOLEAN) { int diff = static_cast(lhs->getIntValue() - rhs->getIntValue()); + if (diff != 0) { if (diff < 0) { return -1; @@ -286,7 +289,10 @@ int triagens::aql::CompareAstNodes (AstNode const* lhs, } } else if (lType == TRI_JSON_STRING) { - return TRI_compare_utf8(lhs->getStringValue(), rhs->getStringValue()); + if (compareUtf8) { + return TRI_compare_utf8(lhs->getStringValue(), rhs->getStringValue()); + } + return strcmp(lhs->getStringValue(), rhs->getStringValue()); } else if (lType == TRI_JSON_ARRAY) { size_t const numLhs = lhs->numMembers(); @@ -294,7 +300,8 @@ int triagens::aql::CompareAstNodes (AstNode const* lhs, size_t const n = ((numLhs > numRhs) ? numRhs : numLhs); for (size_t i = 0; i < n; ++i) { - int res = triagens::aql::CompareAstNodes(lhs->getMember(i), rhs->getMember(i)); + int res = triagens::aql::CompareAstNodes(lhs->getMember(i), rhs->getMember(i), compareUtf8); + if (res != 0) { return res; } @@ -314,7 +321,9 @@ int triagens::aql::CompareAstNodes (AstNode const* lhs, // for array AstNodes) auto lJson = lhs->toJsonValue(TRI_UNKNOWN_MEM_ZONE); auto rJson = lhs->toJsonValue(TRI_UNKNOWN_MEM_ZONE); - int res = TRI_CompareValuesJson(lJson, rJson, true); + + int res = TRI_CompareValuesJson(lJson, rJson, compareUtf8); + if (lJson != nullptr) { TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, lJson); } @@ -590,11 +599,12 @@ void AstNode::sort () { auto const ptr = members._buffer; auto const end = ptr + members._length; + std::sort(ptr, end, [] (void const* lhs, void const* rhs) { auto const l = static_cast(lhs); auto const r = static_cast(rhs); - return (triagens::aql::CompareAstNodes(l, r) < 0); + return (triagens::aql::CompareAstNodes(l, r, false) < 0); }); setFlag(DETERMINED_SORTED, VALUE_SORTED); @@ -606,6 +616,7 @@ void AstNode::sort () { std::string const& AstNode::getTypeString () const { auto it = TypeNames.find(static_cast(type)); + if (it != TypeNames.end()) { return (*it).second; } diff --git a/arangod/Aql/AstNode.h b/arangod/Aql/AstNode.h index 5f198ded6d..253fd4af2b 100644 --- a/arangod/Aql/AstNode.h +++ b/arangod/Aql/AstNode.h @@ -751,7 +751,7 @@ namespace triagens { }; - int CompareAstNodes (AstNode const*, AstNode const*); + int CompareAstNodes (AstNode const*, AstNode const*, bool); } } diff --git a/arangod/Aql/ExecutionBlock.cpp b/arangod/Aql/ExecutionBlock.cpp index 9172aece6a..03892f9ca8 100644 --- a/arangod/Aql/ExecutionBlock.cpp +++ b/arangod/Aql/ExecutionBlock.cpp @@ -1059,13 +1059,18 @@ IndexRangeBlock::IndexRangeBlock (ExecutionEngine* engine, _hasV8Expression(false) { auto trxCollection = _trx->trxCollection(_collection->cid()); + if (trxCollection != nullptr) { _trx->orderBarrier(trxCollection); } - - for (size_t i = 0; i < en->_ranges.size(); i++) { + + std::vector> const& orRanges = en->_ranges; + size_t const n = orRanges.size(); + + for (size_t i = 0; i < n; i++) { _condition->emplace_back(IndexAndCondition()); - for (auto ri: en->_ranges[i]) { + + for (auto const& ri: en->_ranges[i]) { _condition->at(i).emplace_back(ri.clone()); } } @@ -1074,7 +1079,6 @@ IndexRangeBlock::IndexRangeBlock (ExecutionEngine* engine, removeOverlapsIndexOr(*_condition); } - std::vector> const& orRanges = en->_ranges; TRI_ASSERT(en->_index != nullptr); _allBoundsConstant.clear(); @@ -1083,8 +1087,9 @@ IndexRangeBlock::IndexRangeBlock (ExecutionEngine* engine, // Detect, whether all ranges are constant: for (size_t i = 0; i < orRanges.size(); i++) { bool isConstant = true; + std::vector const& attrRanges = orRanges[i]; - for (auto r : attrRanges) { + for (auto const& r : attrRanges) { isConstant &= r.isConstant(); } _anyBoundVariable |= ! isConstant; diff --git a/arangod/Aql/OptimizerRules.cpp b/arangod/Aql/OptimizerRules.cpp index e96b64e5ef..039a1665af 100644 --- a/arangod/Aql/OptimizerRules.cpp +++ b/arangod/Aql/OptimizerRules.cpp @@ -1679,8 +1679,8 @@ static RangeInfoMapVec* BuildRangeInfo (ExecutionPlan* plan, if (enumCollVar != nullptr) { foundSomething = true; - std::unordered_set varsUsed - = Ast::getReferencedVariables(lhs); + std::unordered_set&& varsUsed = Ast::getReferencedVariables(lhs); + if (varsUsed.find(const_cast(enumCollVar)) == varsUsed.end()) { // Found a multiple attribute access of a variable and an @@ -1847,9 +1847,7 @@ static RangeInfoMapVec* BuildRangeInfo (ExecutionPlan* plan, for (size_t i = 0; i < n; i++) { RangeInfo ri(enumCollVar->name, attr.substr(0, attr.size() - 1), - RangeInfoBound(rhs->getMember(i), true), - RangeInfoBound(rhs->getMember(i), true), - true); + RangeInfoBound(rhs->getMember(i), true)); // the following does not seem to be necessary here, but will slow things down // considerably if the array is very big // rimv->differenceRangeInfo(ri); @@ -1863,9 +1861,7 @@ static RangeInfoMapVec* BuildRangeInfo (ExecutionPlan* plan, else { RangeInfo ri(enumCollVar->name, attr.substr(0, attr.size() - 1), - RangeInfoBound(rhs, true), - RangeInfoBound(rhs, true), - true); + RangeInfoBound(rhs, true)); rimv->differenceRangeInfo(ri); if (ri.isValid()) { std::unique_ptr temp(new RangeInfoMap(ri)); @@ -2105,14 +2101,14 @@ class FilterToEnumCollFinder : public WalkerWorker { // results), for example // x.a == 1 || y.c == 2 || x.a == 3 if (_rangeInfoMapVec->isMapped(var->name)) { - std::vector const validPos = _rangeInfoMapVec->validPositions(var->name); + std::vector&& validPos = _rangeInfoMapVec->validPositions(var->name); // are any of the RangeInfoMaps in the vector valid? if (! _canThrow) { if (validPos.empty()) { // ranges are not valid . . . auto parents = node->getParents(); - for (auto x : parents) { + for (auto const& x : parents) { auto noRes = new NoResultsNode(_plan, _plan->nextId()); _plan->registerNode(noRes); _plan->insertDependency(x, noRes); @@ -2127,8 +2123,7 @@ class FilterToEnumCollFinder : public WalkerWorker { // note: prefixes are only used for skiplist indexes // for all other index types, the prefix value will always be 0 - node->getIndexesForIndexRangeNode( - _rangeInfoMapVec->attributes(var->name), idxs, prefixes); + node->getIndexesForIndexRangeNode(_rangeInfoMapVec->attributes(var->name), idxs, prefixes); // make one new plan for every index in that replaces the // enumerate collection node with a IndexRangeNode ... @@ -4347,7 +4342,7 @@ struct RemoveRedundantOr { // returns false if the existing value is better and true if the input value is // better bool compareBounds (AstNodeType type, AstNode const* value, int lowhigh) { - int cmp = CompareAstNodes(bestValue, value); + int cmp = CompareAstNodes(bestValue, value, true); if (cmp == 0 && (isInclusiveBound(comparison) != isInclusiveBound(type))) { return (isInclusiveBound(type) ? true : false); diff --git a/arangod/Aql/RangeInfo.cpp b/arangod/Aql/RangeInfo.cpp index d2cbe6c6f7..3568c36499 100644 --- a/arangod/Aql/RangeInfo.cpp +++ b/arangod/Aql/RangeInfo.cpp @@ -427,7 +427,7 @@ void RangeInfoMap::attributes (std::unordered_set& set, std::unordered_map const* map = find(var); if (map != nullptr) { - for (auto x: *map) { + for (auto const& x: *map) { set.emplace(x.first); } } @@ -527,7 +527,9 @@ bool RangeInfoMapVec::isMapped (std::string const& var) const { std::vector RangeInfoMapVec::validPositions (std::string const& var) const { std::vector valid; - for (size_t i = 0; i < _rangeInfoMapVec.size(); i++) { + size_t const n = _rangeInfoMapVec.size(); + + for (size_t i = 0; i < n; i++) { if (_rangeInfoMapVec[i]->isValid(var)) { valid.emplace_back(i); } diff --git a/arangod/Aql/RangeInfo.h b/arangod/Aql/RangeInfo.h index 1e390b2427..02662b1ddd 100644 --- a/arangod/Aql/RangeInfo.h +++ b/arangod/Aql/RangeInfo.h @@ -373,8 +373,8 @@ namespace triagens { RangeInfo (std::string const& var, std::string const& attr, - RangeInfoBound low, - RangeInfoBound high, + RangeInfoBound const& low, + RangeInfoBound const& high, bool equality) : _var(var), _attr(attr), @@ -414,6 +414,28 @@ namespace triagens { } } } + + RangeInfo (std::string const& var, + std::string const& attr, + RangeInfoBound const& bound) + : _var(var), + _attr(attr), + _valid(true), + _defined(true), + _equality(true) { + + // must be an equality here! + TRI_ASSERT(bound.inclusive()); + + if (bound.isConstant()) { + _lowConst.assign(bound); + _highConst.assign(bound); + } + else { + _lows.emplace_back(bound); + _highs.emplace_back(bound); + } + } RangeInfo (std::string const& var, std::string const& attr)