diff options
author | Charlie Swanson <charlie.swanson@mongodb.com> | 2016-09-28 16:20:30 -0400 |
---|---|---|
committer | Charlie Swanson <charlie.swanson@mongodb.com> | 2016-09-28 16:20:30 -0400 |
commit | 9c8d1cf08ed9b0eeae08b490df67026af40982cd (patch) | |
tree | f59d7a436e4924f7837c98bf414f8f17d846944a | |
parent | 998343374c0351bc7b903ea704c1ac7bbdd12c46 (diff) | |
download | mongo-9c8d1cf08ed9b0eeae08b490df67026af40982cd.tar.gz |
SERVER-26334 fix mongos handling of ntoreturn:1
-rw-r--r-- | jstests/core/tailable_skip_limit.js | 14 | ||||
-rw-r--r-- | jstests/sharding/sharded_limit_batchsize.js | 11 | ||||
-rw-r--r-- | src/mongo/db/query/find.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/query/query_request.cpp | 5 | ||||
-rw-r--r-- | src/mongo/dbtests/querytests.cpp | 26 |
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>(); |