From 08ee53eb0534fcfb5773f9383d20ae1f8609f34d Mon Sep 17 00:00:00 2001 From: Matt Broadstone Date: Tue, 12 Nov 2019 18:12:33 -0500 Subject: [PATCH] fix(bulk): use operation index from input to report operation error The bulk spec requires that the driver report the index of a failed operation according to it's input to the unordered bulk operation. NODE-2308 --- lib/bulk/common.js | 2 +- test/functional/bulk_tests.js | 45 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/lib/bulk/common.js b/lib/bulk/common.js index f2e1a46b93..95ae32a600 100644 --- a/lib/bulk/common.js +++ b/lib/bulk/common.js @@ -475,7 +475,7 @@ function mergeBatchResults(batch, bulkResult, err, result) { if (Array.isArray(result.writeErrors)) { for (let i = 0; i < result.writeErrors.length; i++) { const writeError = { - index: batch.originalZeroIndex + result.writeErrors[i].index, + index: batch.originalIndexes[i], code: result.writeErrors[i].code, errmsg: result.writeErrors[i].errmsg, op: batch.operations[result.writeErrors[i].index] diff --git a/test/functional/bulk_tests.js b/test/functional/bulk_tests.js index 5748d906ad..434f48d40b 100644 --- a/test/functional/bulk_tests.js +++ b/test/functional/bulk_tests.js @@ -1615,4 +1615,49 @@ describe('Bulk', function() { }) .then(() => client.close()); }); + + it('should preserve order of operation index in unordered bulkWrite', function() { + const client = this.configuration.newClient(); + return client.connect().then(() => { + this.defer(() => client.close()); + + const coll = client.db().collection('bulk_write_ordering_test'); + function ignoreNsNotFound(err) { + if (!err.message.match(/ns not found/)) throw err; + } + + return coll + .drop() + .catch(ignoreNsNotFound) + .then(() => coll.insert(Array.from({ length: 4 }, (_, i) => ({ _id: i, a: i })))) + .then(() => + coll + .createIndex({ a: 1 }, { unique: true }) + .then(() => + coll.bulkWrite( + [ + { insertOne: { _id: 5, a: 0 } }, + { updateOne: { filter: { _id: 1 }, update: { $set: { a: 0 } } } }, + { insertOne: { _id: 6, a: 0 } }, + { updateOne: { filter: { _id: 2 }, update: { $set: { a: 0 } } } } + ], + { ordered: false } + ) + ) + ) + .then( + () => { + throw new Error('expected a bulk error'); + }, + err => { + expect(err) + .to.have.property('writeErrors') + .with.length(2); + + expect(err).to.have.nested.property('writeErrors[0].err.index', 0); + expect(err).to.have.nested.property('writeErrors[1].err.index', 2); + } + ); + }); + }); });