Skip to content

Commit 4ac387f

Browse files
authored
feat(java-shell): support cursor.readConcern (#486)
1 parent 9e948e0 commit 4ac387f

File tree

6 files changed

+44
-20
lines changed

6 files changed

+44
-20
lines changed

packages/java-shell/src/main/kotlin/com/mongodb/mongosh/service/BaseMongoIterableHelper.kt

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package com.mongodb.mongosh.service
22

3-
import com.mongodb.CursorType
4-
import com.mongodb.ReadPreference
5-
import com.mongodb.TagSet
3+
import com.mongodb.*
64
import com.mongodb.client.AggregateIterable
75
import com.mongodb.client.FindIterable
86
import com.mongodb.client.MongoDatabase
97
import com.mongodb.client.MongoIterable
108
import com.mongodb.client.model.CountOptions
119
import com.mongodb.mongosh.MongoShellConverter
10+
import com.mongodb.mongosh.result.DocumentResult
1211
import org.bson.Document
1312
import org.graalvm.polyglot.Value
1413

@@ -49,7 +48,7 @@ internal abstract class BaseMongoIterableHelper<T : MongoIterable<*>>(val iterab
4948
open fun tailable(): Unit = throw NotImplementedError("tailable is not supported")
5049
open fun explain(verbosity: String?): Any? = throw NotImplementedError("explain is not supported")
5150
open fun readPrev(v: String, tags: List<TagSet>?): BaseMongoIterableHelper<*> = throw NotImplementedError("readPrev is not supported")
52-
open fun readConcern(v: String, tags: List<TagSet>?): BaseMongoIterableHelper<*> = throw NotImplementedError("readConcern is not supported")
51+
open fun readConcern(v: Value): BaseMongoIterableHelper<*> = throw NotImplementedError("readConcern is not supported")
5352

5453
protected fun set(key: String, value: Any?) {
5554
options[key] = value
@@ -95,6 +94,15 @@ internal class AggregateIterableHelper(iterable: AggregateIterable<*>,
9594
return AggregateIterableHelper(newIterable, converter, options, newCreateOptions)
9695
}
9796

97+
override fun readConcern(v: Value): AggregateIterableHelper {
98+
check(createOptions != null) { "createOptions were not saved" }
99+
if (!v.hasMembers()) throw IllegalArgumentException("document was expected. Got $v")
100+
val newDb = readConcernConverter(createOptions.db, (converter.toJava(v) as DocumentResult).value).getOrThrow()
101+
val newCreateOptions = createOptions.copy(db = newDb)
102+
val newIterable = aggregate(options, newCreateOptions)
103+
return AggregateIterableHelper(newIterable, converter, options, newCreateOptions)
104+
}
105+
98106
override fun maxTimeMS(v: Long) = set("maxTimeMS", v)
99107
override fun comment(v: String) = set("comment", v)
100108
override fun hint(v: Document) = set("hint", v)
@@ -142,6 +150,15 @@ internal class FindIterableHelper(iterable: FindIterable<out Any?>,
142150
return FindIterableHelper(newIterable, converter, options, newCreateOptions)
143151
}
144152

153+
override fun readConcern(v: Value): FindIterableHelper {
154+
check(createOptions != null) { "createOptions were not saved" }
155+
if (!v.hasMembers()) throw IllegalArgumentException("document was expected. Got $v")
156+
val newDb = readConcernConverter(createOptions.db, (converter.toJava(v) as DocumentResult).value).getOrThrow()
157+
val newCreateOptions = createOptions.copy(db = newDb)
158+
val newIterable = find(options, newCreateOptions)
159+
return FindIterableHelper(newIterable, converter, options, newCreateOptions)
160+
}
161+
145162
override fun allowPartialResults() = set("allowPartialResults", true)
146163
override fun oplogReplay() = set("oplogReplay", true)
147164
override fun noCursorTimeout() = set("noCursorTimeout", true)

packages/java-shell/src/main/kotlin/com/mongodb/mongosh/service/Cursor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,9 @@ internal class Cursor(private var helper: BaseMongoIterableHelper<*>, private va
231231
}
232232

233233
@HostAccess.Export
234-
override fun withReadConcern(v: String): Cursor {
234+
override fun withReadConcern(v: Value): Cursor {
235235
checkQueryNotExecuted()
236-
helper = helper.readConcern(v, null)
236+
helper = helper.readConcern(v)
237237
return this
238238
}
239239

packages/java-shell/src/main/kotlin/com/mongodb/mongosh/service/ServiceProviderCursor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ interface ServiceProviderCursor {
2929
fun project(v: Value): ServiceProviderCursor
3030
fun returnKey(v: Value): ServiceProviderCursor
3131
fun withReadPreference(v: String): ServiceProviderCursor
32-
fun withReadConcern(v: String): ServiceProviderCursor
32+
fun withReadConcern(v: Value): ServiceProviderCursor
3333
fun showRecordId(v: Boolean): ServiceProviderCursor
3434
fun size(): Value
3535
fun skip(v: Int): ServiceProviderCursor

packages/java-shell/src/main/kotlin/com/mongodb/mongosh/service/optionConverters.kt

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,26 @@ internal val writeConcernConverters: Map<String, (MongoDatabase, Any?) -> Either
5858

5959
internal val writeConcernDefaultConverter = unrecognizedField<MongoDatabase>("write concern")
6060

61+
62+
internal val readConcernConverter: (MongoDatabase, Any?) -> Either<MongoDatabase> = { db, value ->
63+
if (value is Map<*, *>) convert(db, readConcernConverters, readConcernDefaultConverter, value)
64+
else Left(CommandException("invalid parameter: expected an object (readConcern)", "FailedToParse"))
65+
}
66+
67+
internal val readConcernConverters: Map<String, (MongoDatabase, Any?) -> Either<MongoDatabase>> = mapOf(
68+
typed("level", String::class.java) { db, value ->
69+
db.withReadConcern(ReadConcern(ReadConcernLevel.fromString(value)))
70+
}
71+
)
72+
73+
internal val readConcernDefaultConverter = unrecognizedField<MongoDatabase>("read concern")
74+
75+
6176
internal val dbConverters: Map<String, (MongoDatabase, Any?) -> Either<MongoDatabase>> = mapOf(
6277
typed("writeConcern", Map::class.java) { db, value ->
6378
convert(db, writeConcernConverters, writeConcernDefaultConverter, value).getOrThrow()
6479
},
65-
"readConcern" to { db, value ->
66-
if (value is Map<*, *>) convert(db, readConcernConverters, readConcernDefaultConverter, value)
67-
else Left(CommandException("invalid parameter: expected an object (readConcern)", "FailedToParse"))
68-
},
80+
"readConcern" to readConcernConverter,
6981
"readPreference" to { db, value ->
7082
if (value is Map<*, *>) convert(db, readPreferenceConverters, readPreferenceDefaultConverter, value)
7183
else Left(CommandException("invalid parameter: expected an object (readPreference)", "FailedToParse"))
@@ -74,14 +86,6 @@ internal val dbConverters: Map<String, (MongoDatabase, Any?) -> Either<MongoData
7486

7587
internal val dbDefaultConverter = unrecognizedField<MongoDatabase>("db options")
7688

77-
internal val readConcernConverters: Map<String, (MongoDatabase, Any?) -> Either<MongoDatabase>> = mapOf(
78-
typed("level", String::class.java) { db, value ->
79-
db.withReadConcern(ReadConcern(ReadConcernLevel.fromString(value)))
80-
}
81-
)
82-
83-
internal val readConcernDefaultConverter = unrecognizedField<MongoDatabase>("read concern")
84-
8589
internal fun <T> unrecognizedField(objectName: String): (T, String, Any?) -> Either<T> = { _, key, _ ->
8690
Left(CommandException("unrecognized $objectName field: $key", "FailedToParse"))
8791
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
org.graalvm.polyglot.PolyglotException: Error: Setting readConcern on the cursor is not currently supported. See NODE-2806
1+
[ { "_id": <ObjectID>, "a": 1 } ]
2+
java.lang.IllegalArgumentException: 'unknown' is not a valid readConcernLevel

packages/java-shell/src/test/resources/cursor/readConcern-ignored.js renamed to packages/java-shell/src/test/resources/cursor/readConcern.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@ db.coll.drop();
33
db.coll.insertOne({a: 1});
44
// command
55
db.coll.find().readConcern('local');
6+
// command
7+
db.coll.find().readConcern('unknown');
68
// clear
79
db.coll.drop();

0 commit comments

Comments
 (0)