From b2ec5d6f1b13ec208735a861d13d5e83daf4d3fd Mon Sep 17 00:00:00 2001 From: James Date: Sat, 6 Dec 2014 20:25:14 +0000 Subject: [PATCH] more cleaning up --- arangod/Aql/ExecutionBlock.cpp | 22 ++- arangod/Aql/RangeInfo.cpp | 288 +++++++++++---------------------- arangod/Aql/RangeInfo.h | 11 +- 3 files changed, 117 insertions(+), 204 deletions(-) diff --git a/arangod/Aql/ExecutionBlock.cpp b/arangod/Aql/ExecutionBlock.cpp index 78d9ccf484..aacf98c1b1 100644 --- a/arangod/Aql/ExecutionBlock.cpp +++ b/arangod/Aql/ExecutionBlock.cpp @@ -1072,7 +1072,12 @@ bool IndexRangeBlock::initRanges () { RangeInfoBound(json), RangeInfoBound(json), true); - differenceRangeInfoVecRangeInfo(riv, ri); + for (auto oldRi: riv) { + differenceRangeInfos(oldRi, ri); + if (! ri.isValid()) { + break; + } + } if (ri.isValid()) { riv.push_back(ri); } @@ -1119,11 +1124,16 @@ bool IndexRangeBlock::initRanges () { ("isConstant", Json(true)) ("bound", bound.at(static_cast(j)).copy()); auto ri = RangeInfo(r._var, - r._attr, - RangeInfoBound(json), - RangeInfoBound(json), - true); - differenceRangeInfoVecRangeInfo(riv, ri); + r._attr, + RangeInfoBound(json), + RangeInfoBound(json), + true); + for (auto oldRi: riv) { + differenceRangeInfos(oldRi, ri); + if (! ri.isValid()) { + break; + } + } if (ri.isValid()) { riv.push_back(ri); } diff --git a/arangod/Aql/RangeInfo.cpp b/arangod/Aql/RangeInfo.cpp index 5acf739823..7c964def46 100644 --- a/arangod/Aql/RangeInfo.cpp +++ b/arangod/Aql/RangeInfo.cpp @@ -341,11 +341,19 @@ void RangeInfoMap::erase (RangeInfo* ri) { RangeInfoMap* RangeInfoMap::clone () { auto rim = new RangeInfoMap(); - for (auto x: _ranges) { - for (auto y: x.second) { - rim->insert(y.second.clone()); + + try { + for (auto x: _ranges) { + for (auto y: x.second) { + rim->insert(y.second.clone()); + } } } + catch (...) { + delete rim; + throw; + } + return rim; } @@ -464,7 +472,7 @@ std::unordered_map* RangeInfoMapVec::find ( } //////////////////////////////////////////////////////////////////////////////// -/// @brief isMapped: returns true if in every RIM in the vector +/// @brief isMapped: returns true if is in every RIM in the vector //////////////////////////////////////////////////////////////////////////////// bool RangeInfoMapVec::isMapped(std::string const& var) { @@ -493,7 +501,7 @@ std::vector RangeInfoMapVec::validPositions(std::string const& var) { } //////////////////////////////////////////////////////////////////////////////// -/// @brief attributes: returns a vector of the names of the attributes for the +/// @brief attributes: returns the set of names of the attributes for the /// variable var stored in the RIM vector. //////////////////////////////////////////////////////////////////////////////// @@ -538,21 +546,27 @@ RangeInfoMapVec* triagens::aql::orCombineRangeInfoMapVecs (RangeInfoMapVec* lhs, //avoid inserting overlapping conditions for (size_t i = 0; i < rhs->size(); i++) { auto rim = new RangeInfoMap(); - for (auto x: (*rhs)[i]->_ranges) { - for (auto y: x.second) { - // take the difference of - RangeInfo ri = y.second.clone(); - lhs->differenceRangeInfo(ri); - if (ri.isValid()) { - // if ri is nullptr, then y.second is contained in an existing ri - rim->insert(ri); + try { + for (auto x: (*rhs)[i]->_ranges) { + for (auto y: x.second) { + // take the difference of + RangeInfo ri = y.second.clone(); + lhs->differenceRangeInfo(ri); + if (ri.isValid()) { + // if ri is nullptr, then y.second is contained in an existing ri + rim->insert(ri); + } } } + if (! rim->empty()) { + lhs->emplace_back(rim); + } else { + delete rim; + } } - if (! rim->empty()) { - lhs->emplace_back(rim); - } else { + catch (...) { delete rim; + throw; } } delete rhs; @@ -621,11 +635,11 @@ RangeInfoMapVec* triagens::aql::andCombineRangeInfoMapVecs (RangeInfoMapVec* lhs // returns -1 if lhs is a (not necessarily proper) subset of rhs, 0 if neither is // contained in the other, and, 1 if rhs is contained in lhs. -static int containmentRangeInfos (RangeInfo* lhs, RangeInfo* rhs) { +static int containmentRangeInfos (RangeInfo const& lhs, RangeInfo const& rhs) { - int LoLo = CompareRangeInfoBound(lhs->_lowConst, rhs->_lowConst, -1); + int LoLo = CompareRangeInfoBound(lhs._lowConst, rhs._lowConst, -1); // -1 if lhs is tighter than rhs, 1 if rhs tighter than lhs - int HiHi = CompareRangeInfoBound(lhs->_highConst, rhs->_highConst, 1); + int HiHi = CompareRangeInfoBound(lhs._highConst, rhs._highConst, 1); // -1 if lhs is tighter than rhs, 1 if rhs tighter than lhs // 0 if equal if (LoLo == HiHi) { @@ -637,14 +651,14 @@ static int containmentRangeInfos (RangeInfo* lhs, RangeInfo* rhs) { // returns true if the constant parts of lhs and rhs are disjoint and false // otherwise -static bool areDisjointRangeInfos (RangeInfo* lhs, RangeInfo* rhs) { +static bool areDisjointRangeInfos (RangeInfo const& lhs, RangeInfo const& rhs) { int HiLo; - if (lhs->_highConst.isDefined() && rhs->_lowConst.isDefined()) { - HiLo = TRI_CompareValuesJson(lhs->_highConst.bound().json(), - rhs->_lowConst.bound().json()); + if (lhs._highConst.isDefined() && rhs._lowConst.isDefined()) { + HiLo = TRI_CompareValuesJson(lhs._highConst.bound().json(), + rhs._lowConst.bound().json()); if ((HiLo == -1) || - (HiLo == 0 && (! lhs->_highConst.inclusive() ||! rhs->_lowConst.inclusive()))) { + (HiLo == 0 && (! lhs._highConst.inclusive() ||! rhs._lowConst.inclusive()))) { return true; } } @@ -652,11 +666,11 @@ static bool areDisjointRangeInfos (RangeInfo* lhs, RangeInfo* rhs) { //else compare lhs low > rhs high int LoHi; - if (lhs->_lowConst.isDefined() && rhs->_highConst.isDefined()) { - LoHi = TRI_CompareValuesJson(lhs->_lowConst.bound().json(), - rhs->_highConst.bound().json()); + if (lhs._lowConst.isDefined() && rhs._highConst.isDefined()) { + LoHi = TRI_CompareValuesJson(lhs._lowConst.bound().json(), + rhs._highConst.bound().json()); return (LoHi == 1) || - (LoHi == 0 && (! lhs->_lowConst.inclusive() ||! rhs->_highConst.inclusive())); + (LoHi == 0 && (! lhs._lowConst.inclusive() ||! rhs._highConst.inclusive())); } // in this case, either: // a) lhs.hi defined and rhs.lo undefined; or @@ -676,180 +690,66 @@ static bool areDisjointRangeInfos (RangeInfo* lhs, RangeInfo* rhs) { //////////////////////////////////////////////////////////////////////////////// /// @brief differenceRangeInfo: returns the difference of the constant parts of -/// the given RangeInfo and the union of the RangeInfos (for the same var and -/// attr) in the vector. The method invalidates newRi if it is empty. +/// the given RangeInfos. /// -/// Modifies newRi in-place. +/// Modifies either lhs or rhs in place, so that the constant parts of lhs +/// and rhs are disjoint, and the union of the modified lhs and rhs equals the +/// union of the originals. //////////////////////////////////////////////////////////////////////////////// +void triagens::aql::differenceRangeInfos (RangeInfo& lhs, RangeInfo& rhs) { + TRI_ASSERT(lhs._var == lhs._var); + TRI_ASSERT(lhs._attr == rhs._attr); + + if (! areDisjointRangeInfos(lhs, rhs)) { + int contained = containmentRangeInfos(lhs, rhs); + if (contained == -1) { + // lhs is a subset of rhs, disregard lhs + // unassign _lowConst and _highConst + if (lhs.isConstant()) { + lhs.invalidate(); + } else { + RangeInfoBound rib; + lhs._lowConst.assign(rib); + lhs._highConst.assign(rib); + } + } + else if (contained == 1) { + // rhs is a subset of lhs, disregard rhs + // unassign _lowConst and _highConst + if (rhs.isConstant()) { + rhs.invalidate(); + } else { + RangeInfoBound rib; + rhs._lowConst.assign(rib); + rhs._highConst.assign(rib); + } + } + else { + // lhs and rhs have non-empty intersection + int LoLo = CompareRangeInfoBound(lhs._lowConst, rhs._lowConst, -1); + if (LoLo == 1) { // replace low bound of new with high bound of old + rhs._lowConst.assign(lhs._highConst); + rhs._lowConst.setInclude(! lhs._highConst.inclusive()); + } + else { // replace the high bound of the new with the low bound of the old + rhs._highConst.assign(lhs._lowConst); + rhs._highConst.setInclude(! lhs._lowConst.inclusive()); + } + } + } +} + void RangeInfoMapVec::differenceRangeInfo (RangeInfo& newRi) { for (auto rim: _rangeInfoMapVec) { RangeInfo* oldRi = rim->find(newRi._var, newRi._attr); - if (oldRi != nullptr && ! areDisjointRangeInfos(oldRi, &newRi)) { - int contained = containmentRangeInfos(oldRi, &newRi); - if (contained == -1) { - // oldRi is a subset of newRi, erase the old RI - // continuing finding the difference of the new one and existing RIs - if (oldRi->isConstant()) { - rim->erase(oldRi); - } - else { - // unassign _lowConst and _highConst - RangeInfoBound rib; - oldRi->_lowConst.assign(rib); - oldRi->_highConst.assign(rib); - } - } - else if (contained == 1) { - // newRi is a subset of oldRi, disregard new - if (newRi.isConstant()) { - newRi.invalidate(); - return; - } - else { - // unassign _lowConst and _highConst - RangeInfoBound rib; - newRi._lowConst.assign(rib); - newRi._highConst.assign(rib); - return; - } - } - else { - // oldRi and newRi have non-empty intersection - int LoLo = CompareRangeInfoBound(oldRi->_lowConst, newRi._lowConst, -1); - if (LoLo == 1) { // replace low bound of new with high bound of old - newRi._lowConst.assign(oldRi->_highConst); - newRi._lowConst.setInclude(! oldRi->_highConst.inclusive()); - } - else { // replace the high bound of the new with the low bound of the old - newRi._highConst.assign(oldRi->_lowConst); - newRi._highConst.setInclude(! oldRi->_lowConst.inclusive()); - } + if (oldRi != nullptr) { + differenceRangeInfos(*oldRi, newRi); + if (! newRi.isValid() || + (newRi._lowConst.bound().isEmpty() && newRi._highConst.bound().isEmpty())){ + break; } } } } - -void triagens::aql::differenceRangeInfoVecRangeInfo (std::vector& riv, - RangeInfo& newRi) { - TRI_ASSERT(newRi.isConstant()); // only apply this to constant range infos! - - for (auto oldRi: riv) { - TRI_ASSERT(oldRi.isConstant()); - if (! areDisjointRangeInfos(&oldRi, &newRi)) { - int contained = containmentRangeInfos(&oldRi, &newRi); - if (contained == -1) { - // oldRi is a subset of newRi, erase the old RI - oldRi.invalidate(); - // continuing finding the difference of the new one and existing RIs - } - else if (contained == 1) { - // newRi is a subset of oldRi, disregard new - newRi.invalidate(); - return; - } - else { - // oldRi and newRi have non-empty intersection - int LoLo = CompareRangeInfoBound(oldRi._lowConst, newRi._lowConst, -1); - if (LoLo == 1) { // replace low bound of new with high bound of old - newRi._lowConst.assign(oldRi._highConst); - newRi._lowConst.setInclude(! oldRi._highConst.inclusive()); - } - else { // replace the high bound of the new with the low bound of the old - newRi._highConst.assign(oldRi._lowConst); - newRi._highConst.setInclude(! oldRi._lowConst.inclusive()); - } - } - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief differenceIndexOrAndRangeInfo: analogue of differenceRangeInfo -//////////////////////////////////////////////////////////////////////////////// - -void triagens::aql::differenceIndexOrAndRangeInfo (IndexOrCondition* orCond, - RangeInfo& newRi) { - - for (IndexAndCondition andCond: *orCond) { - for (size_t i = 0; i < andCond.size(); i++) { - RangeInfo oldRi = andCond[i]; - if (! areDisjointRangeInfos(&oldRi, &newRi)) { - int contained = containmentRangeInfos(&oldRi, &newRi); - if (contained == -1) { - // oldRi is a subset of newRi, erase the old RI - // continuing finding the difference of the new one and existing RIs - if (oldRi.isConstant()) { - oldRi.invalidate(); - } - else { - // unassign _lowConst and _highConst - RangeInfoBound rib; - oldRi._lowConst.assign(rib); - oldRi._highConst.assign(rib); - } - } - else if (contained == 1) { - // newRi is a subset of oldRi, disregard new - if (newRi.isConstant()) { - newRi.invalidate(); - return; // i.e. do nothing on return of this function - } else { - // unassign _lowConst and _highConst - RangeInfoBound rib; - newRi._lowConst.assign(rib); - newRi._highConst.assign(rib); - return; - } - } - else { - // oldRi and newRi have non-empty intersection - int LoLo = CompareRangeInfoBound(oldRi._lowConst, newRi._lowConst, -1); - if (LoLo == 1) { // replace low bound of new with high bound of old - newRi._lowConst.assign(oldRi._highConst); - newRi._lowConst.setInclude(! oldRi._highConst.inclusive()); - } - else { // replace the high bound of the new with the low bound of the old - newRi._highConst.assign(oldRi._lowConst); - newRi._highConst.setInclude(! oldRi._lowConst.inclusive()); - } - } - } - } - } - return; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief orCombineIndexOrAndIndexAnd: analogue of orCombineRangeInfoMapVecs -//////////////////////////////////////////////////////////////////////////////// - -void triagens::aql::orCombineIndexOrAndIndexAnd ( - IndexOrCondition* orCond, IndexAndCondition andCond) { - - if (orCond->empty()) { - orCond->push_back(andCond); - return; - } - - if (andCond.empty()) { - return; - } - - //avoid inserting overlapping ranges - IndexAndCondition newAnd; - for (RangeInfo x: andCond) { - differenceIndexOrAndRangeInfo(orCond, x); - if (x.isValid()) { - // if ri is invalid, then it is contained in an existing ri - newAnd.emplace_back(x); - } - } - - if (! newAnd.empty()) { - orCond->emplace_back(newAnd); - } -} - - diff --git a/arangod/Aql/RangeInfo.h b/arangod/Aql/RangeInfo.h index ffc056b40e..dfad625241 100644 --- a/arangod/Aql/RangeInfo.h +++ b/arangod/Aql/RangeInfo.h @@ -929,12 +929,15 @@ namespace triagens { typedef std::vector IndexOrCondition; //////////////////////////////////////////////////////////////////////////////// -/// @brief orCombineIndexOrAndIndexAnd: analogue of orCombineRangeInfoMapVecs +/// @brief differenceRangeInfo: returns the difference of the constant parts of +/// the given RangeInfos. +/// +/// Modifies either lhs or rhs in place, so that the constant parts of lhs +/// and rhs are disjoint, and the union of the modified lhs and rhs equals the +/// union of the originals. //////////////////////////////////////////////////////////////////////////////// - void orCombineIndexOrAndIndexAnd(IndexOrCondition*, IndexAndCondition); - void differenceIndexOrAndRangeInfo(IndexOrCondition*, RangeInfo&); - void differenceRangeInfoVecRangeInfo(std::vector&, RangeInfo&); + void differenceRangeInfos (RangeInfo&, RangeInfo&); } }