Skip to content

Commit 5565c46

Browse files
committed
Fix reporting _id for Bulk API edge case for pre-2.6 servers
When upserted _id is not returned on custom _id's JAVA-1263
1 parent 79120a5 commit 5565c46

File tree

2 files changed

+68
-5
lines changed

2 files changed

+68
-5
lines changed

src/main/com/mongodb/DBCollectionImpl.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,9 @@ BulkWriteResult executeWriteCommandProtocol() {
734734
@Override
735735
WriteResult executeWriteProtocol(final int i) {
736736
ModifyRequest update = updateRequests.get(i);
737-
return update(update.getQuery(), update.getUpdateDocument(), update.isUpsert(), update.isMulti(), writeConcern,
738-
encoder);
737+
WriteResult writeResult = update(update.getQuery(), update.getUpdateDocument(), update.isUpsert(),
738+
update.isMulti(), writeConcern, encoder);
739+
return addMissingUpserted(update, writeResult);
739740
}
740741

741742
@Override
@@ -759,8 +760,9 @@ BulkWriteResult executeWriteCommandProtocol() {
759760
@Override
760761
WriteResult executeWriteProtocol(final int i) {
761762
ModifyRequest update = replaceRequests.get(i);
762-
return update(update.getQuery(), update.getUpdateDocument(), update.isUpsert(), update.isMulti(), writeConcern,
763-
encoder);
763+
WriteResult writeResult = update(update.getQuery(), update.getUpdateDocument(), update.isUpsert(),
764+
update.isMulti(), writeConcern, encoder);
765+
return addMissingUpserted(update, writeResult);
764766
}
765767

766768
@Override
@@ -921,6 +923,26 @@ private DBObject getErrorResponseDetails(final DBObject response) {
921923
}
922924
return details;
923925
}
926+
927+
WriteResult addMissingUpserted(final ModifyRequest update, final WriteResult writeResult) {
928+
// On pre 2.6 servers upserts with custom _id's would be not be reported so we check if _id
929+
// was in the update query or the find query then massage the writeResult.
930+
if (update.isUpsert() && writeConcern.callGetLastError() && !writeResult.isUpdateOfExisting()
931+
&& writeResult.getUpsertedId() == null) {
932+
DBObject updateDocument = update.getUpdateDocument();
933+
DBObject query = update.getQuery();
934+
if (updateDocument.containsField("_id")) {
935+
CommandResult commandResult = writeResult.getLastError();
936+
commandResult.put("upserted", updateDocument.get("_id"));
937+
return new WriteResult(commandResult, writeResult.getLastConcern());
938+
} else if (query.containsField("_id")) {
939+
CommandResult commandResult = writeResult.getLastError();
940+
commandResult.put("upserted", query.get("_id"));
941+
return new WriteResult(commandResult, writeResult.getLastConcern());
942+
}
943+
}
944+
return writeResult;
945+
}
924946
}
925947
}
926948
}

src/test/com/mongodb/BulkWriteOperationSpecification.groovy

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,47 @@ class BulkWriteOperationSpecification extends FunctionalSpecification {
351351
ordered << [true, false]
352352
}
353353

354+
def 'when a custom _id is upserted it should be in the write result'() {
355+
given:
356+
def operation = initializeBulkOperation(ordered)
357+
operation.find(new BasicDBObject('_id', 0)).upsert()
358+
.updateOne(new BasicDBObject('$set', new BasicDBObject('a', 0)))
359+
operation.find(new BasicDBObject('a', 1)).upsert().replaceOne(new BasicDBObject('_id', 1))
360+
operation.find(new BasicDBObject('_id', 2)).upsert().replaceOne(new BasicDBObject('_id', 2))
361+
362+
when:
363+
def result = operation.execute()
364+
365+
then:
366+
result == new AcknowledgedBulkWriteResult(UPDATE, 0, expectedModifiedCount(0), [new BulkWriteUpsert(0, 0),
367+
new BulkWriteUpsert(1, 1),
368+
new BulkWriteUpsert(2, 2)])
369+
collection.count() == 3
370+
371+
where:
372+
ordered << [true, false]
373+
}
374+
375+
def 'unacknowledged upserts with custom _id should not error'() {
376+
given:
377+
def operation = initializeBulkOperation(ordered)
378+
operation.find(new BasicDBObject('_id', 0)).upsert()
379+
.updateOne(new BasicDBObject('$set', new BasicDBObject('a', 0)))
380+
operation.find(new BasicDBObject('a', 1)).upsert().replaceOne(new BasicDBObject('_id', 1))
381+
operation.find(new BasicDBObject('_id', 2)).upsert().replaceOne(new BasicDBObject('_id', 2))
382+
383+
when:
384+
def result = operation.execute(WriteConcern.UNACKNOWLEDGED)
385+
collection.insert(new BasicDBObject('_id', 4))
386+
387+
then:
388+
result == new UnacknowledgedBulkWriteResult()
389+
collection.count() == 4
390+
391+
where:
392+
ordered << [true, false]
393+
}
394+
354395
def 'when a replacement document is 16MB, the document is still replaced'() {
355396
given:
356397
collection.insert(new BasicDBObject('_id', 1))
@@ -813,4 +854,4 @@ class BulkWriteOperationSpecification extends FunctionalSpecification {
813854
private static Integer expectedModifiedCount(final int expectedCountForServersThatSupportIt) {
814855
(serverIsAtLeastVersion(2.5)) ? expectedCountForServersThatSupportIt : null
815856
}
816-
}
857+
}

0 commit comments

Comments
 (0)