diff options
author | Hari Khalsa <hkhalsa@10gen.com> | 2013-10-08 19:28:44 -0400 |
---|---|---|
committer | Hari Khalsa <hkhalsa@10gen.com> | 2013-10-09 11:02:54 -0400 |
commit | 3c831f3014fe9502a1ec78afce0448757bf7d7f7 (patch) | |
tree | a708b1faf28dc5c2aa134f3f997f14fe04b2786e /src/mongo/db | |
parent | 3aa47f21fa5d0370cd7a0ef277e7d1d8d359edbb (diff) | |
download | mongo-3c831f3014fe9502a1ec78afce0448757bf7d7f7.tar.gz |
SERVER-10471 fix intervals generated for minkey/maxkey lt(e) gt(e), modify spigot
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/query/index_bounds_builder.cpp | 46 | ||||
-rw-r--r-- | src/mongo/db/query/new_find.cpp | 28 |
2 files changed, 67 insertions, 7 deletions
diff --git a/src/mongo/db/query/index_bounds_builder.cpp b/src/mongo/db/query/index_bounds_builder.cpp index 89e3e8cdc6a..1734ef8a2be 100644 --- a/src/mongo/db/query/index_bounds_builder.cpp +++ b/src/mongo/db/query/index_bounds_builder.cpp @@ -224,9 +224,17 @@ namespace mongo { else if (MatchExpression::LTE == expr->matchType()) { const LTEMatchExpression* node = static_cast<const LTEMatchExpression*>(expr); BSONElement dataElt = node->getData(); + + // Everything is <= MaxKey. + if (MaxKey == dataElt.type()) { + oilOut->intervals.push_back(allValues()); + *exactOut = true; + return; + } + BSONObjBuilder bob; bob.appendMinForType("", dataElt.type()); - bob.append(dataElt); + bob.appendAs(dataElt, ""); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); oilOut->intervals.push_back(makeRangeInterval(dataObj, true, true)); @@ -236,11 +244,20 @@ namespace mongo { else if (MatchExpression::LT == expr->matchType()) { const LTMatchExpression* node = static_cast<const LTMatchExpression*>(expr); BSONElement dataElt = node->getData(); + + // Everything is <= MaxKey. + if (MaxKey == dataElt.type()) { + oilOut->intervals.push_back(allValues()); + *exactOut = true; + return; + } + BSONObjBuilder bob; bob.appendMinForType("", dataElt.type()); - bob.append(dataElt); + bob.appendAs(dataElt, ""); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); + cout << "data obj is " << dataObj.toString() << endl; oilOut->intervals.push_back(makeRangeInterval(dataObj, true, false)); // XXX: only exact if not (null or array) *exactOut = true; @@ -248,8 +265,16 @@ namespace mongo { else if (MatchExpression::GT == expr->matchType()) { const GTMatchExpression* node = static_cast<const GTMatchExpression*>(expr); BSONElement dataElt = node->getData(); + + // Everything is > MinKey. + if (MinKey == dataElt.type()) { + oilOut->intervals.push_back(allValues()); + *exactOut = true; + return; + } + BSONObjBuilder bob; - bob.append(node->getData()); + bob.appendAs(node->getData(), ""); bob.appendMaxForType("", dataElt.type()); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); @@ -261,8 +286,15 @@ namespace mongo { const GTEMatchExpression* node = static_cast<const GTEMatchExpression*>(expr); BSONElement dataElt = node->getData(); + // Everything is >= MinKey. + if (MinKey == dataElt.type()) { + oilOut->intervals.push_back(allValues()); + *exactOut = true; + return; + } + BSONObjBuilder bob; - bob.append(dataElt); + bob.appendAs(dataElt, ""); bob.appendMaxForType("", dataElt.type()); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); @@ -464,8 +496,8 @@ namespace mongo { // We want to merge intervals i and i+1. // Interval 'i' starts before interval 'i+1'. BSONObjBuilder bob; - bob.append(iv[i].start); - bob.append(iv[i + 1].end); + bob.appendAs(iv[i].start, ""); + bob.appendAs(iv[i + 1].end, ""); BSONObj data = bob.obj(); bool startInclusive = iv[i].startInclusive; bool endInclusive = iv[i + i].endInclusive; @@ -505,7 +537,7 @@ namespace mongo { // static BSONObj IndexBoundsBuilder::objFromElement(const BSONElement& elt) { BSONObjBuilder bob; - bob.append(elt); + bob.appendAs(elt, ""); return bob.obj(); } diff --git a/src/mongo/db/query/new_find.cpp b/src/mongo/db/query/new_find.cpp index 4d1f81c52de..c0814cb22d5 100644 --- a/src/mongo/db/query/new_find.cpp +++ b/src/mongo/db/query/new_find.cpp @@ -35,6 +35,7 @@ #include "mongo/db/index/index_descriptor.h" #include "mongo/db/keypattern.h" #include "mongo/db/kill_current_op.h" +#include "mongo/db/matcher/expression.h" #include "mongo/db/query/cached_plan_runner.h" #include "mongo/db/query/canonical_query.h" #include "mongo/db/query/eof_runner.h" @@ -101,6 +102,18 @@ namespace mongo { bool isNewQueryFrameworkEnabled() { return newQueryFrameworkEnabled; } void enableNewQueryFramework() { newQueryFrameworkEnabled = true; } + bool hasNode(MatchExpression* root, MatchExpression::MatchType type) { + if (type == root->matchType()) { + return true; + } + for (size_t i = 0; i < root->numChildren(); ++i) { + if (hasNode(root->getChild(i), type)) { + return true; + } + } + return false; + } + // Do we use the old or the new? I call this the spigot. bool canUseNewSystem(const QueryMessage& qm, CanonicalQuery** cqOut) { CanonicalQuery* cq; @@ -125,6 +138,21 @@ namespace mongo { return false; } + if (hasNode(cq->root(), MatchExpression::NOT) + || hasNode(cq->root(), MatchExpression::NOR)) { + + cout << "rejecting query w/negation\n"; + return false; + } + + if (pq.returnKey() || pq.showDiskLoc() || (0 != pq.getMaxScan()) || !pq.getMin().isEmpty() + || !pq.getMax().isEmpty()) { + cout << "rejecting wacky query args query\n"; + return false; + } + + // XXX: 2d. + *cqOut = scopedCq.release(); return true; } |