diff --git a/arangod/Aql/Ast.cpp b/arangod/Aql/Ast.cpp index bd4590c3cf..4a03a04467 100644 --- a/arangod/Aql/Ast.cpp +++ b/arangod/Aql/Ast.cpp @@ -2229,8 +2229,8 @@ AstNode* Ast::nodeFromJson (TRI_json_t const* json) { size_t const n = json->_value._objects._length; for (size_t i = 0; i < n; i += 2) { - TRI_json_t const* key = static_cast(TRI_AddressVector(&json->_value._objects, i)); - TRI_json_t const* value = static_cast(TRI_AddressVector(&json->_value._objects, i + 1)); + auto key = static_cast(TRI_AddressVector(&json->_value._objects, i)); + auto value = static_cast(TRI_AddressVector(&json->_value._objects, i + 1)); if (! TRI_IsStringJson(key) || value == nullptr) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unexpected type found in object node"); diff --git a/arangod/Aql/ExecutionBlock.cpp b/arangod/Aql/ExecutionBlock.cpp index 660d0d35ca..61bcb6bb0b 100644 --- a/arangod/Aql/ExecutionBlock.cpp +++ b/arangod/Aql/ExecutionBlock.cpp @@ -1145,10 +1145,13 @@ void IndexRangeBlock::buildExpressions () { // collect the evaluated bounds here for (size_t k = 0; k < n; k++) { auto const& r = en->_ranges[i][k]; - // First create a new RangeInfo containing only the constant - // low and high bound of r: - RangeInfo riConst(r._var, r._attr, r._lowConst, r._highConst, r.is1ValueRangeInfo()); - collector[k].emplace_back(riConst); + + { + // First create a new RangeInfo containing only the constant + // low and high bound of r: + RangeInfo riConst(r._var, r._attr, r._lowConst, r._highConst, r.is1ValueRangeInfo()); + collector[k].emplace_back(std::move(riConst)); + } // Now work the actual values of the variable lows and highs into // this constant range: @@ -1200,7 +1203,7 @@ void IndexRangeBlock::buildExpressions () { true)); } - collector[k] = andCombineRangeInfoVecs(collector[k], riv); + collector[k] = std::move(andCombineRangeInfoVecs(collector[k], riv)); } } @@ -1250,7 +1253,8 @@ void IndexRangeBlock::buildExpressions () { RangeInfoBound(h.inclusive(), true, b2), // will steal b2's JSON true)); } - collector[k] = andCombineRangeInfoVecs(collector[k], riv); + + collector[k] = std::move(andCombineRangeInfoVecs(collector[k], riv)); } } @@ -1270,6 +1274,8 @@ void IndexRangeBlock::buildExpressions () { // otherwise the condition is impossible to fulfill // the elements of the direct product of the collector are and // conditions which should be added to newCondition + + // create cartesian product std::unique_ptr indexAnds(cartesian(collector)); if (newCondition == nullptr) { @@ -1277,15 +1283,15 @@ void IndexRangeBlock::buildExpressions () { } else { for (auto const& indexAnd: *indexAnds) { - newCondition->emplace_back(indexAnd); + newCondition->emplace_back(std::move(indexAnd)); } } } + } - freeCondition(); - + if (newCondition != nullptr) { _condition = newCondition.release(); _freeCondition = true; @@ -1294,7 +1300,6 @@ void IndexRangeBlock::buildExpressions () { removeOverlapsIndexOr(*_condition); } else { - // create at least an empty condition _condition = new IndexOrCondition; _freeCondition = true; } @@ -1313,28 +1318,26 @@ int IndexRangeBlock::initialize () { _allVariableBoundExpressions.clear(); // instanciate expressions: - auto instanciateExpression = [&] (RangeInfoBound& b) -> void { + auto instanciateExpression = [&] (RangeInfoBound const& b) -> void { AstNode const* a = b.getExpressionAst(_engine->getQuery()->ast()); // all new AstNodes are registered with the Ast in the Query - auto e = new Expression(_engine->getQuery()->ast(), a); - try { - TRI_IF_FAILURE("IndexRangeBlock::initialize") { - THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG); - } - _allVariableBoundExpressions.emplace_back(e); - } - catch (...) { - delete e; - throw; + std::unique_ptr e(new Expression(_engine->getQuery()->ast(), a)); + + TRI_IF_FAILURE("IndexRangeBlock::initialize") { + THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG); } + _allVariableBoundExpressions.emplace_back(e.get()); + auto expression = e.release(); + // Prepare _inVars and _inRegs: _inVars.emplace_back(); std::vector& inVarsCur = _inVars.back(); _inRegs.emplace_back(); std::vector& inRegsCur = _inRegs.back(); - std::unordered_set inVars = e->variables(); + std::unordered_set inVars = expression->variables(); + for (auto v : inVars) { inVarsCur.emplace_back(v); auto it = getPlanNode()->getRegisterPlan()->varInfo.find(v->id); @@ -1342,7 +1345,6 @@ int IndexRangeBlock::initialize () { TRI_ASSERT(it->second.registerId < ExecutionNode::MaxRegisterId); inRegsCur.emplace_back(it->second.registerId); } - }; // Get the ranges from the node: @@ -1352,11 +1354,11 @@ int IndexRangeBlock::initialize () { for (size_t i = 0; i < orRanges.size(); i++) { if (! _allBoundsConstant[i]) { try { - for (auto r : orRanges[i]) { - for (auto l : r._lows) { + for (auto const& r : orRanges[i]) { + for (auto const& l : r._lows) { instanciateExpression(l); } - for (auto h : r._highs) { + for (auto const& h : r._highs) { instanciateExpression(h); } } @@ -1504,13 +1506,17 @@ void IndexRangeBlock::sortConditions () { for (size_t s = 0; s < n; s++) { _sortCoords.emplace_back(s); - std::vector next; TRI_IF_FAILURE("IndexRangeBlock::sortConditions") { THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG); } - next.reserve(numFields); - prefix.emplace_back(next); + + { + std::vector next; + next.reserve(numFields); + prefix.emplace_back(std::move(next)); + } + // prefix[s][t] = position in _condition[s] corresponding to the th index // field for (size_t t = 0; t < numFields; t++) { @@ -1595,6 +1601,12 @@ bool IndexRangeBlock::SortFunc::operator() (size_t const& i, size_t const& j) co std::vector IndexRangeBlock::andCombineRangeInfoVecs (std::vector const& riv1, std::vector const& riv2) const { std::vector out; + + std::unordered_set cache( + 16, + triagens::basics::JsonHash(), + triagens::basics::JsonEqual() + ); for (RangeInfo const& ri1: riv1) { for (RangeInfo const& ri2: riv2) { @@ -1605,10 +1617,21 @@ std::vector IndexRangeBlock::andCombineRangeInfoVecs (std::vector inVars = _expression->variables(); + std::unordered_set const& inVars = _expression->variables(); _inVars.reserve(inVars.size()); _inRegs.reserve(inVars.size()); diff --git a/arangod/Aql/Functions.cpp b/arangod/Aql/Functions.cpp index 2db6825b08..1cab4924b6 100644 --- a/arangod/Aql/Functions.cpp +++ b/arangod/Aql/Functions.cpp @@ -39,28 +39,6 @@ using namespace triagens::aql; using Json = triagens::basics::Json; -//////////////////////////////////////////////////////////////////////////////// -/// @brief hasher for JSON value -//////////////////////////////////////////////////////////////////////////////// - -struct JsonHash { - size_t operator() (TRI_json_t const* value) const { - return TRI_FastHashJson(value); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief equality comparator for JSON values -//////////////////////////////////////////////////////////////////////////////// - -struct JsonEqual { - bool operator() (TRI_json_t const* lhs, - TRI_json_t const* rhs) const { - int res = TRI_CompareValuesJson(lhs, rhs, false); - return (res == 0); - } -}; - //////////////////////////////////////////////////////////////////////////////// /// @brief register warning //////////////////////////////////////////////////////////////////////////////// @@ -855,7 +833,11 @@ AqlValue Functions::Unique (triagens::aql::Query* query, TRI_json_t const* valueJson = value.json(); size_t const n = valueJson->_value._objects._length; - std::unordered_set values(512, JsonHash(), JsonEqual()); + std::unordered_set values( + 512, + triagens::basics::JsonHash(), + triagens::basics::JsonEqual() + ); for (size_t i = 0; i < n; ++i) { auto value = static_cast(TRI_AddressVector(&valueJson->_value._objects, i)); @@ -941,7 +923,11 @@ AqlValue Functions::UnionDistinct (triagens::aql::Query* query, triagens::arango::AqlTransaction* trx, TRI_document_collection_t const* collection, AqlValue const parameters) { - std::unordered_set values(512, JsonHash(), JsonEqual()); + std::unordered_set values( + 512, + triagens::basics::JsonHash(), + triagens::basics::JsonEqual() + ); size_t const n = parameters.arraySize(); @@ -993,7 +979,11 @@ AqlValue Functions::Intersection (triagens::aql::Query* query, triagens::arango::AqlTransaction* trx, TRI_document_collection_t const* collection, AqlValue const parameters) { - std::unordered_set values(512, JsonHash(), JsonEqual()); + std::unordered_set values( + 512, + triagens::basics::JsonHash(), + triagens::basics::JsonEqual() + ); size_t const n = parameters.arraySize(); diff --git a/arangod/Aql/RangeInfo.cpp b/arangod/Aql/RangeInfo.cpp index 6cc8fda212..b67c3e3149 100644 --- a/arangod/Aql/RangeInfo.cpp +++ b/arangod/Aql/RangeInfo.cpp @@ -239,15 +239,17 @@ void RangeInfo::fuse (RangeInfo const& that) { // First sort out the constant low bounds: _lowConst.andCombineLowerBounds(that._lowConst); + // Simply append the variable ones: - for (auto l : that._lows) { + for (auto const& l : that._lows) { _lows.emplace_back(l); } // Sort out the constant high bounds: _highConst.andCombineUpperBounds(that._highConst); + // Simply append the variable ones: - for (auto h : that._highs) { + for (auto const& h : that._highs) { _highs.emplace_back(h); } @@ -307,8 +309,8 @@ RangeInfoMap::RangeInfoMap (RangeInfo const& ri) : void RangeInfoMap::insert (std::string const& var, std::string const& name, - RangeInfoBound low, - RangeInfoBound high, + RangeInfoBound const& low, + RangeInfoBound const& high, bool equality) { insert(RangeInfo(var, name, low, high, equality)); } @@ -601,11 +603,12 @@ RangeInfoMapVec* triagens::aql::orCombineRangeInfoMapVecs (RangeInfoMapVec* lhs, delete rhs; return lhs; } + + try { + // avoid inserting overlapping conditions + for (size_t i = 0; i < rhs->size(); i++) { + std::unique_ptr rim(new RangeInfoMap()); - //avoid inserting overlapping conditions - for (size_t i = 0; i < rhs->size(); i++) { - auto rim = new RangeInfoMap(); - try { for (auto x: (*rhs)[i]->_ranges) { for (auto y: x.second) { RangeInfo ri = y.second.clone(); @@ -613,20 +616,20 @@ RangeInfoMapVec* triagens::aql::orCombineRangeInfoMapVecs (RangeInfoMapVec* lhs, } } if (! rim->empty()) { - lhs->emplace_back(rim); + lhs->emplace_back(rim.get()); + rim.release(); } - else { - delete rim; - } } - catch (...) { - delete rim; - throw; - } - } - delete rhs; - return lhs; + delete rhs; + return lhs; + } + catch (...) { + // avoid leaking + delete lhs; + delete rhs; + throw; + } } //////////////////////////////////////////////////////////////////////////////// @@ -673,7 +676,7 @@ RangeInfoMapVec* triagens::aql::andCombineRangeInfoMapVecs (RangeInfoMapVec* lhs std::unique_ptr rimv(new RangeInfoMapVec()); // must be a new one for (size_t i = 0; i < lhs->size(); i++) { for (size_t j = 0; j < rhs->size(); j++) { - rimv->emplace_back(andCombineRangeInfoMaps((*lhs)[i]->clone(), (*rhs)[j]->clone())); + rimv->emplace_back(std::move(andCombineRangeInfoMaps((*lhs)[i]->clone(), (*rhs)[j]->clone()))); } } @@ -866,7 +869,7 @@ bool triagens::aql::areDisjointIndexAndConditions (IndexAndCondition const& and1 IndexAndCondition const& and2) { for (auto const& ri1: and1) { for (auto const& ri2: and2) { - if (ri2._attr == ri1._attr) { + if (ri2._var == ri1._var && ri2._attr == ri1._attr) { if (areDisjointRangeInfos(ri1, ri2)) { return true; } @@ -888,7 +891,7 @@ bool triagens::aql::isContainedIndexAndConditions (IndexAndCondition const& and1 bool contained = false; for (auto const& ri2: and2) { - if (ri2._attr == ri1._attr) { + if (ri2._var == ri1._var && ri2._attr == ri1._attr) { if (ContainmentRangeInfos(ri2, ri1) == 1) { contained = true; break; @@ -1051,7 +1054,7 @@ void triagens::aql::removeOverlapsIndexOr (IndexOrCondition& ioc) { } } - // remove empty + // remove empty bounds ioc.erase(std::remove_if(ioc.begin(), ioc.end(), [] (IndexAndCondition const& item) -> bool { return item.empty(); }), ioc.end()); diff --git a/arangod/Aql/RangeInfo.h b/arangod/Aql/RangeInfo.h index ce15d58f44..4dd304d344 100644 --- a/arangod/Aql/RangeInfo.h +++ b/arangod/Aql/RangeInfo.h @@ -734,7 +734,7 @@ namespace triagens { auto it = map->find(attr); - if (it == map->end()){ + if (it == map->end()) { return nullptr; } @@ -751,8 +751,8 @@ namespace triagens { void insert (std::string const& var, std::string const& name, - RangeInfoBound low, - RangeInfoBound high, + RangeInfoBound const& low, + RangeInfoBound const& high, bool equality); //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/Basics/json-utilities.h b/lib/Basics/json-utilities.h index 43f3c9d991..86c65d02b5 100644 --- a/lib/Basics/json-utilities.h +++ b/lib/Basics/json-utilities.h @@ -164,6 +164,34 @@ uint64_t TRI_HashJsonByAttributes (TRI_json_t const* json, bool docComplete, int* error); +//////////////////////////////////////////////////////////////////////////////// +/// @brief hasher for JSON value +//////////////////////////////////////////////////////////////////////////////// + +namespace triagens { + namespace basics { + + struct JsonHash { + size_t operator() (TRI_json_t const* value) const { + return TRI_FastHashJson(value); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief equality comparator for JSON values +//////////////////////////////////////////////////////////////////////////////// + + struct JsonEqual { + bool operator() (TRI_json_t const* lhs, + TRI_json_t const* rhs) const { + int res = TRI_CompareValuesJson(lhs, rhs, false); + return (res == 0); + } + }; + + } +} + #endif // -----------------------------------------------------------------------------