diff options
Diffstat (limited to 'src/mongo/db/query/index_bounds.cpp')
| -rw-r--r-- | src/mongo/db/query/index_bounds.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/mongo/db/query/index_bounds.cpp b/src/mongo/db/query/index_bounds.cpp index ef8eeb6d8b8..b8b7e4bce74 100644 --- a/src/mongo/db/query/index_bounds.cpp +++ b/src/mongo/db/query/index_bounds.cpp @@ -32,6 +32,7 @@ #include <tuple> #include <utility> +#include "mongo/base/simple_string_data_comparator.h" #include "mongo/bson/simple_bsonobj_comparator.h" namespace mongo { @@ -163,6 +164,21 @@ BoundInclusion IndexBounds::makeBoundInclusionFromBoundBools(bool startKeyInclus } } +BoundInclusion IndexBounds::reverseBoundInclusion(BoundInclusion b) { + switch (b) { + case BoundInclusion::kIncludeStartKeyOnly: + return BoundInclusion::kIncludeEndKeyOnly; + case BoundInclusion::kIncludeEndKeyOnly: + return BoundInclusion::kIncludeStartKeyOnly; + case BoundInclusion::kIncludeBothStartAndEndKeys: + case BoundInclusion::kExcludeBothStartAndEndKeys: + // These are both symmetric. + return b; + default: + MONGO_UNREACHABLE; + } +} + bool OrderedIntervalList::operator==(const OrderedIntervalList& other) const { if (this->name != other.name) { @@ -186,6 +202,38 @@ bool OrderedIntervalList::operator!=(const OrderedIntervalList& other) const { return !(*this == other); } +void OrderedIntervalList::reverse() { + for (size_t i = 0; i < (intervals.size() + 1) / 2; i++) { + const size_t otherIdx = intervals.size() - i - 1; + intervals[i].reverse(); + if (i != otherIdx) { + intervals[otherIdx].reverse(); + std::swap(intervals[i], intervals[otherIdx]); + } + } +} + +OrderedIntervalList OrderedIntervalList::reverseClone() const { + OrderedIntervalList clone(name); + + for (auto it = intervals.rbegin(); it != intervals.rend(); ++it) { + clone.intervals.push_back(it->reverseClone()); + } + + return clone; +} + +Interval::Direction OrderedIntervalList::computeDirection() const { + for (auto&& iv : intervals) { + const auto dir = iv.getDirection(); + if (dir != Interval::Direction::kDirectionNone) { + return dir; + } + } + + return Interval::Direction::kDirectionNone; +} + // static void OrderedIntervalList::complement() { BSONObjBuilder minBob; @@ -299,6 +347,40 @@ BSONObj IndexBounds::toBSON() const { return bob.obj(); } +IndexBounds IndexBounds::forwardize() const { + IndexBounds newBounds; + newBounds.isSimpleRange = isSimpleRange; + + if (isSimpleRange) { + const int cmpRes = startKey.woCompare(endKey); + if (cmpRes <= 0) { + newBounds.startKey = startKey; + newBounds.endKey = endKey; + newBounds.boundInclusion = boundInclusion; + } else { + // Swap start and end key. + newBounds.endKey = startKey; + newBounds.startKey = endKey; + newBounds.boundInclusion = IndexBounds::reverseBoundInclusion(boundInclusion); + } + + return newBounds; + } + + newBounds.fields.reserve(fields.size()); + std::transform(fields.begin(), + fields.end(), + std::back_inserter(newBounds.fields), + [](const OrderedIntervalList& oil) -> OrderedIntervalList { + if (oil.computeDirection() == Interval::Direction::kDirectionDescending) { + return oil.reverseClone(); + } + return oil; + }); + + return newBounds; +} + // // Validity checking for bounds // |
