summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/index_bounds.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/query/index_bounds.cpp')
-rw-r--r--src/mongo/db/query/index_bounds.cpp82
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
//