summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Swanson <charlie.swanson@mongodb.com>2016-09-28 16:20:30 -0400
committerCharlie Swanson <charlie.swanson@mongodb.com>2016-09-28 16:20:30 -0400
commit9c8d1cf08ed9b0eeae08b490df67026af40982cd (patch)
treef59d7a436e4924f7837c98bf414f8f17d846944a
parent998343374c0351bc7b903ea704c1ac7bbdd12c46 (diff)
downloadmongo-9c8d1cf08ed9b0eeae08b490df67026af40982cd.tar.gz
SERVER-26334 fix mongos handling of ntoreturn:1
-rw-r--r--jstests/core/tailable_skip_limit.js14
-rw-r--r--jstests/sharding/sharded_limit_batchsize.js11
-rw-r--r--src/mongo/db/query/find.cpp6
-rw-r--r--src/mongo/db/query/query_request.cpp5
-rw-r--r--src/mongo/dbtests/querytests.cpp26
5 files changed, 31 insertions, 31 deletions
diff --git a/jstests/core/tailable_skip_limit.js b/jstests/core/tailable_skip_limit.js
index f771621ad83..7e09d1bfbfa 100644
--- a/jstests/core/tailable_skip_limit.js
+++ b/jstests/core/tailable_skip_limit.js
@@ -58,6 +58,20 @@
assert.throws(function() {
t.find().addOption(2).limit(-100).next();
});
+ assert.throws(function() {
+ t.find().addOption(2).limit(-1).itcount();
+ });
+
+ // When using read commands, a limit of 1 with the tailable option is allowed. In legacy
+ // readMode, an ntoreturn of 1 means the same thing as ntoreturn -1 and is disallowed with
+ // tailable.
+ if (db.getMongo().useReadCommands()) {
+ assert.eq(1, t.find().addOption(2).limit(1).itcount());
+ } else {
+ assert.throws(function() {
+ t.find().addOption(2).limit(1).itcount();
+ });
+ }
// Tests that a tailable cursor over an empty capped collection produces a dead cursor, intended
// to be run on both mongod and mongos. For SERVER-20720.
diff --git a/jstests/sharding/sharded_limit_batchsize.js b/jstests/sharding/sharded_limit_batchsize.js
index cd636b56cdc..a3fe4f5906f 100644
--- a/jstests/sharding/sharded_limit_batchsize.js
+++ b/jstests/sharding/sharded_limit_batchsize.js
@@ -41,6 +41,17 @@
assert.eq(2, cursor.next()["_id"]);
assert.eq(3, cursor.next()["_id"]);
assert(!cursor.hasNext());
+
+ // Ensure that in the limit 1 case, which is special when in legacy readMode, the server
+ // does not leave a cursor open.
+ var openCursorsBefore =
+ assert.commandWorked(coll.getDB().serverStatus()).metrics.cursor.open.total;
+ cursor = coll.find().sort({x: 1}).limit(1);
+ assert(cursor.hasNext());
+ assert.eq(-10, cursor.next()["_id"]);
+ var openCursorsAfter =
+ assert.commandWorked(coll.getDB().serverStatus()).metrics.cursor.open.total;
+ assert.eq(openCursorsBefore, openCursorsAfter);
}
//
diff --git a/src/mongo/db/query/find.cpp b/src/mongo/db/query/find.cpp
index 14645bd55e1..bbce97fc50b 100644
--- a/src/mongo/db/query/find.cpp
+++ b/src/mongo/db/query/find.cpp
@@ -89,11 +89,7 @@ bool shouldSaveCursor(OperationContext* txn,
}
const QueryRequest& qr = exec->getCanonicalQuery()->getQueryRequest();
- if (!qr.wantMore() && !qr.isTailable()) {
- return false;
- }
-
- if (qr.getNToReturn().value_or(0) == 1) {
+ if (!qr.wantMore()) {
return false;
}
diff --git a/src/mongo/db/query/query_request.cpp b/src/mongo/db/query/query_request.cpp
index b0aa759e853..af2c46b550c 100644
--- a/src/mongo/db/query/query_request.cpp
+++ b/src/mongo/db/query/query_request.cpp
@@ -734,6 +734,11 @@ Status QueryRequest::init(int ntoskip,
}
}
+ // An ntoreturn of 1 is special because it also means to return at most one batch.
+ if (_ntoreturn.value_or(0) == 1) {
+ _wantMore = false;
+ }
+
// Initialize flags passed as 'queryOptions' bit vector.
initFromInt(queryOptions);
diff --git a/src/mongo/dbtests/querytests.cpp b/src/mongo/dbtests/querytests.cpp
index de55f54f45d..cd2f902372a 100644
--- a/src/mongo/dbtests/querytests.cpp
+++ b/src/mongo/dbtests/querytests.cpp
@@ -416,31 +416,6 @@ public:
}
};
-class ReturnOneOfManyAndTail : public ClientBase {
-public:
- ~ReturnOneOfManyAndTail() {
- _client.dropCollection("unittests.querytests.ReturnOneOfManyAndTail");
- }
- void run() {
- const char* ns = "unittests.querytests.ReturnOneOfManyAndTail";
- _client.createCollection(ns, 1024, true);
- insert(ns, BSON("a" << 0));
- insert(ns, BSON("a" << 1));
- insert(ns, BSON("a" << 2));
- unique_ptr<DBClientCursor> c =
- _client.query(ns,
- QUERY("a" << GT << 0).hint(BSON("$natural" << 1)),
- 1,
- 0,
- 0,
- QueryOption_CursorTailable);
- // If only one result requested, a cursor is not saved.
- ASSERT_EQUALS(0, c->getCursorId());
- ASSERT(c->more());
- ASSERT_EQUALS(1, c->next().getIntField("a"));
- }
-};
-
class TailNotAtEnd : public ClientBase {
public:
~TailNotAtEnd() {
@@ -1783,7 +1758,6 @@ public:
add<GetMoreKillOp>();
add<GetMoreInvalidRequest>();
add<PositiveLimit>();
- add<ReturnOneOfManyAndTail>();
add<TailNotAtEnd>();
add<EmptyTail>();
add<TailableDelete>();