diff --git a/driver-coroutines/src/jvmMain/kotlin/CoroutineMongoCollectionImpl.kt b/driver-coroutines/src/jvmMain/kotlin/CoroutineMongoCollectionImpl.kt index f3489db8..13b75ea0 100644 --- a/driver-coroutines/src/jvmMain/kotlin/CoroutineMongoCollectionImpl.kt +++ b/driver-coroutines/src/jvmMain/kotlin/CoroutineMongoCollectionImpl.kt @@ -170,6 +170,8 @@ private class CoroutineMongoCollectionImpl( model.documents, model.options.toJava(), ) + } catch (e: com.mongodb.MongoBulkWriteException) { + throw e.toKtMongo(model, fullyQualifiedName) } catch (e: com.mongodb.MongoCommandException) { throw e.toKtMongo(model, fullyQualifiedName, factory) } diff --git a/driver-shared-official/src/jvmMain/kotlin/Exceptions.jvm.kt b/driver-shared-official/src/jvmMain/kotlin/Exceptions.jvm.kt index e6937d07..26da51b7 100644 --- a/driver-shared-official/src/jvmMain/kotlin/Exceptions.jvm.kt +++ b/driver-shared-official/src/jvmMain/kotlin/Exceptions.jvm.kt @@ -22,6 +22,7 @@ import opensavvy.ktmongo.dsl.command.Command import opensavvy.ktmongo.dsl.command.errors.MongoException import opensavvy.ktmongo.dsl.command.errors.MongoSyntaxException import opensavvy.ktmongo.dsl.command.errors.MongoWriteException +import com.mongodb.MongoBulkWriteException as OfficialMongoBulkWriteException import com.mongodb.MongoCommandException as OfficialMongoCommandException import com.mongodb.MongoWriteException as OfficialMongoWriteException import com.mongodb.ServerAddress as OfficialServerAddress @@ -64,6 +65,25 @@ fun OfficialMongoWriteException.toKtMongo( ) } +@LowLevelApi +fun OfficialMongoBulkWriteException.toKtMongo( + command: Command, + namespace: String, +): MongoWriteException { + return MongoWriteException( + server = serverAddress.toKtMongo(), + command = command, + errors = writeErrors.map { + WriteErrorDataImpl( + code = it.code, + message = it.message, + ) + }, + namespace = namespace, + cause = this, + ) +} + @LowLevelApi fun OfficialMongoCommandException.toKtMongo( command: Command, diff --git a/driver-sync/src/jvmMain/kotlin/SyncMongoCollectionImpl.kt b/driver-sync/src/jvmMain/kotlin/SyncMongoCollectionImpl.kt index 905440ff..5258a365 100644 --- a/driver-sync/src/jvmMain/kotlin/SyncMongoCollectionImpl.kt +++ b/driver-sync/src/jvmMain/kotlin/SyncMongoCollectionImpl.kt @@ -170,6 +170,8 @@ private class SyncMongoCollectionImpl( model.documents, model.options.toJava(), ) + } catch (e: com.mongodb.MongoBulkWriteException) { + throw e.toKtMongo(model, fullyQualifiedName) } catch (e: com.mongodb.MongoCommandException) { throw e.toKtMongo(model, fullyQualifiedName, factory) } diff --git a/test/src/commonMain/kotlin/operations/InsertOperations.test.kt b/test/src/commonMain/kotlin/operations/InsertOperations.test.kt index 559d8124..9404d0d5 100644 --- a/test/src/commonMain/kotlin/operations/InsertOperations.test.kt +++ b/test/src/commonMain/kotlin/operations/InsertOperations.test.kt @@ -105,6 +105,28 @@ fun SuiteDsl.verifyInsertOperations( check(e.namespace == collection().fullyQualifiedName) } + test("insertMany • Cannot insert two documents with the same ID") { + val id = collection().newId() + + val alice = InsertOperationsUser( + _id = id, + name = "Alice", + ) + + val bob = InsertOperationsUser( + _id = id, + name = "Bob", + ) + + val e = checkThrows { + collection().insertMany(alice, bob) + } + check((e.command as? InsertMany<*>)?.documents == listOf(alice, bob)) + check(e.errors.size == 1) + check(e.errors[0].code == 11000) + check(e.namespace == collection().fullyQualifiedName) + } + test("insertOne • Cannot set invalid options") { val e = checkThrows { collection().insertOne(