Skip to content

Commit c841b55

Browse files
committed
Ensure all DBCollectionFindOptions are applied correctly
JAVA-2329
1 parent aa670f9 commit c841b55

File tree

2 files changed

+129
-33
lines changed

2 files changed

+129
-33
lines changed

driver/src/main/com/mongodb/DBCursor.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -485,13 +485,11 @@ private FindOperation<DBObject> getQueryOperation(final Decoder<DBObject> decode
485485
.batchSize(findOptions.getBatchSize())
486486
.skip(findOptions.getSkip())
487487
.limit(findOptions.getLimit())
488+
.maxAwaitTime(findOptions.getMaxAwaitTime(MILLISECONDS), MILLISECONDS)
488489
.maxTime(findOptions.getMaxTime(MILLISECONDS), MILLISECONDS)
489490
.modifiers(collection.wrapAllowNull(findOptions.getModifiers()))
490491
.projection(collection.wrapAllowNull(findOptions.getProjection()))
491492
.sort(collection.wrapAllowNull(findOptions.getSort()))
492-
.noCursorTimeout(findOptions.isNoCursorTimeout())
493-
.oplogReplay(findOptions.isOplogReplay())
494-
.partial(findOptions.isPartial())
495493
.collation(findOptions.getCollation());
496494

497495
if ((this.options & Bytes.QUERYOPTION_TAILABLE) != 0) {
@@ -500,15 +498,23 @@ private FindOperation<DBObject> getQueryOperation(final Decoder<DBObject> decode
500498
} else {
501499
operation.cursorType(CursorType.Tailable);
502500
}
501+
} else {
502+
operation.cursorType(findOptions.getCursorType());
503503
}
504504
if ((this.options & Bytes.QUERYOPTION_OPLOGREPLAY) != 0) {
505505
operation.oplogReplay(true);
506+
} else {
507+
operation.oplogReplay(findOptions.isOplogReplay());
506508
}
507509
if ((this.options & Bytes.QUERYOPTION_NOTIMEOUT) != 0) {
508510
operation.noCursorTimeout(true);
511+
} else {
512+
operation.noCursorTimeout(findOptions.isNoCursorTimeout());
509513
}
510514
if ((this.options & Bytes.QUERYOPTION_PARTIAL) != 0) {
511515
operation.partial(true);
516+
} else {
517+
operation.partial(findOptions.isPartial());
512518
}
513519
return operation;
514520
}

driver/src/test/unit/com/mongodb/DBCursorSpecification.groovy

Lines changed: 120 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@
1717
package com.mongodb
1818

1919
import com.mongodb.client.model.Collation
20+
import com.mongodb.client.model.DBCollectionFindOptions
2021
import com.mongodb.operation.BatchCursor
2122
import com.mongodb.operation.CountOperation
2223
import com.mongodb.operation.FindOperation
2324
import org.bson.BsonDocument
2425
import spock.lang.Specification
2526

27+
import java.util.concurrent.TimeUnit
28+
2629
import static com.mongodb.CustomMatchers.isTheSameAs
2730
import static com.mongodb.Fixture.getMongoClient
2831
import static spock.util.matcher.HamcrestSupport.expect
@@ -109,59 +112,34 @@ class DBCursorSpecification extends Specification {
109112

110113
def 'find should create the correct FindOperation'() {
111114
given:
112-
def dbObject = new BasicDBObject('_id', 1)
113-
def executor = new TestOperationExecutor([Stub(BatchCursor) {
114-
def count = 0
115-
next() >> {
116-
count++
117-
[dbObject]
118-
}
119-
hasNext() >> {
120-
count == 0
121-
}
122-
getServerCursor() >> {
123-
null
124-
}
125-
}]);
115+
def executor = new TestOperationExecutor([stubBatchCursor()]);
126116
def collection = new DB(getMongoClient(), 'myDatabase', executor).getCollection('test')
127117
def cursor = new DBCursor(collection, new BasicDBObject(), new BasicDBObject(), ReadPreference.primary())
128118
cursor.setReadConcern(ReadConcern.MAJORITY)
129119

130120
when:
131-
def results = cursor.toArray()
121+
cursor.toArray()
132122

133123
then:
134-
results == [dbObject]
135124
expect executor.getReadOperation(), isTheSameAs(new FindOperation(collection.getNamespace(), collection.getObjectCodec())
136125
.readConcern(ReadConcern.MAJORITY)
137126
.filter(new BsonDocument())
138127
.projection(new BsonDocument())
139128
.modifiers(new BsonDocument()))
140129
}
141130

131+
142132
def 'one should create the correct FindOperation'() {
143133
given:
144-
def dbObject = new BasicDBObject('_id', 1)
145-
def executor = new TestOperationExecutor([Stub(BatchCursor) {
146-
def count = 0
147-
next() >> {
148-
count++
149-
[dbObject]
150-
}
151-
hasNext() >> {
152-
count == 0
153-
}
154-
getServerCursor() >> new ServerCursor(12L, new ServerAddress())
155-
}]);
134+
def executor = new TestOperationExecutor([stubBatchCursor()]);
156135
def collection = new DB(getMongoClient(), 'myDatabase', executor).getCollection('test')
157136
def cursor = new DBCursor(collection, new BasicDBObject(), new BasicDBObject(), ReadPreference.primary())
158137
cursor.setReadConcern(ReadConcern.MAJORITY)
159138

160139
when:
161-
def result = cursor.one()
140+
cursor.one()
162141

163142
then:
164-
result == dbObject
165143
expect executor.getReadOperation(), isTheSameAs(new FindOperation(collection.getNamespace(), collection.getObjectCodec())
166144
.readConcern(ReadConcern.MAJORITY)
167145
.limit(-1)
@@ -170,6 +148,104 @@ class DBCursorSpecification extends Specification {
170148
.modifiers(new BsonDocument()))
171149
}
172150

151+
def 'DBCollectionFindOptions should be used to create the expected operation'() {
152+
given:
153+
def executor = new TestOperationExecutor([stubBatchCursor()]);
154+
def collection = new DB(getMongoClient(), 'myDatabase', executor).getCollection('test')
155+
def collation = Collation.builder().locale('en').build()
156+
def cursorType = CursorType.NonTailable
157+
def filter = new BasicDBObject()
158+
def projection = BasicDBObject.parse('{a: 1, _id: 0}')
159+
def sort = BasicDBObject.parse('{a: 1}')
160+
def modifiers = BasicDBObject.parse('{$comment: 1}')
161+
def bsonFilter = new BsonDocument()
162+
def bsonModifiers = BsonDocument.parse(modifiers.toJson())
163+
def bsonProjection = BsonDocument.parse(projection.toJson())
164+
def bsonSort = BsonDocument.parse(sort.toJson())
165+
def readConcern = ReadConcern.LOCAL
166+
def readPreference = ReadPreference.nearest()
167+
def findOptions = new DBCollectionFindOptions()
168+
.batchSize(1)
169+
.collation(collation)
170+
.cursorType(cursorType)
171+
.limit(1)
172+
.maxAwaitTime(1, TimeUnit.MILLISECONDS)
173+
.maxTime(1, TimeUnit.MILLISECONDS)
174+
.modifiers(modifiers)
175+
.noCursorTimeout(true)
176+
.oplogReplay(true)
177+
.partial(true)
178+
.projection(projection)
179+
.readConcern(readConcern)
180+
.readPreference(readPreference)
181+
.skip(1)
182+
.sort(sort)
183+
def cursor = new DBCursor(collection, filter, findOptions)
184+
185+
when:
186+
cursor.toArray()
187+
188+
then:
189+
expect executor.getReadOperation(), isTheSameAs(new FindOperation(collection.getNamespace(), collection.getObjectCodec())
190+
.batchSize(1)
191+
.collation(collation)
192+
.cursorType(cursorType)
193+
.filter(bsonFilter)
194+
.limit(1)
195+
.maxAwaitTime(1, TimeUnit.MILLISECONDS)
196+
.maxTime(1, TimeUnit.MILLISECONDS)
197+
.modifiers(bsonModifiers)
198+
.noCursorTimeout(true)
199+
.oplogReplay(true)
200+
.partial(true)
201+
.projection(bsonProjection)
202+
.readConcern(readConcern)
203+
.skip(1)
204+
.sort(bsonSort)
205+
)
206+
207+
executor.getReadPreference() == findOptions.getReadPreference()
208+
}
209+
210+
def 'DBCursor options should override DBCollectionFindOptions'() {
211+
given:
212+
def executor = new TestOperationExecutor([stubBatchCursor()]);
213+
def collection = new DB(getMongoClient(), 'myDatabase', executor).getCollection('test')
214+
def cursorType = CursorType.NonTailable
215+
def readPreference = ReadPreference.primary()
216+
def filter = new BasicDBObject()
217+
def bsonFilter = new BsonDocument()
218+
def findOptions = new DBCollectionFindOptions()
219+
.cursorType(cursorType)
220+
.noCursorTimeout(false)
221+
.oplogReplay(false)
222+
.partial(false)
223+
.readPreference(readPreference)
224+
225+
def cursor = new DBCursor(collection, filter , findOptions)
226+
.addOption(Bytes.QUERYOPTION_AWAITDATA)
227+
.addOption(Bytes.QUERYOPTION_NOTIMEOUT)
228+
.addOption(Bytes.QUERYOPTION_OPLOGREPLAY)
229+
.addOption(Bytes.QUERYOPTION_PARTIAL)
230+
.addOption(Bytes.QUERYOPTION_SLAVEOK)
231+
.addOption(Bytes.QUERYOPTION_TAILABLE)
232+
233+
when:
234+
cursor.toArray()
235+
236+
then:
237+
expect executor.getReadOperation(), isTheSameAs(new FindOperation(collection.getNamespace(), collection.getObjectCodec())
238+
.modifiers(new BsonDocument())
239+
.cursorType(CursorType.TailableAwait)
240+
.filter(bsonFilter)
241+
.noCursorTimeout(true)
242+
.oplogReplay(true)
243+
.partial(true)
244+
)
245+
246+
executor.getReadPreference() == ReadPreference.secondaryPreferred()
247+
}
248+
173249
def 'count should create the correct CountOperation'() {
174250
def executor = new TestOperationExecutor([42L]);
175251
def collection = new DB(getMongoClient(), 'myDatabase', executor).getCollection('test')
@@ -201,4 +277,18 @@ class DBCursorSpecification extends Specification {
201277
.readConcern(ReadConcern.MAJORITY)
202278
.filter(new BsonDocument()))
203279
}
280+
281+
private stubBatchCursor() {
282+
Stub(BatchCursor) {
283+
def count = 0
284+
next() >> {
285+
count++
286+
[new BasicDBObject('_id', 1)]
287+
}
288+
hasNext() >> {
289+
count == 0
290+
}
291+
getServerCursor() >> new ServerCursor(12L, new ServerAddress())
292+
};
293+
}
204294
}

0 commit comments

Comments
 (0)