Skip to content

Commit e01cafd

Browse files
authored
fix: apply bson options for bulk operations (#2601)
The logic for inheriting BSON options was refactored for bulk operations, ensuring proper inheritance of BSON Serialize options. NODE-1561
1 parent f921132 commit e01cafd

File tree

3 files changed

+123
-32
lines changed

3 files changed

+123
-32
lines changed

src/bulk/common.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PromiseProvider } from '../promise_provider';
2-
import { Long, ObjectId, Document } from '../bson';
2+
import { Long, ObjectId, Document, BSONSerializeOptions, resolveBSONOptions } from '../bson';
33
import { MongoError, MongoWriteConcernError, AnyError } from '../error';
44
import {
55
applyWriteConcern,
@@ -570,7 +570,11 @@ function executeCommands(
570570
executeCommands(bulkOperation, options, callback);
571571
}
572572

573-
const finalOptions = Object.assign({ ordered: bulkOperation.isOrdered }, options);
573+
const finalOptions = Object.assign(
574+
{ ordered: bulkOperation.isOrdered },
575+
bulkOperation.bsonOptions,
576+
options
577+
);
574578
if (bulkOperation.s.writeConcern != null) {
575579
finalOptions.writeConcern = bulkOperation.s.writeConcern;
576580
}
@@ -584,16 +588,6 @@ function executeCommands(
584588
resultHandler.operationId = bulkOperation.operationId;
585589
}
586590

587-
// Serialize functions
588-
if (bulkOperation.s.options.serializeFunctions) {
589-
finalOptions.serializeFunctions = true;
590-
}
591-
592-
// Ignore undefined
593-
if (bulkOperation.s.options.ignoreUndefined) {
594-
finalOptions.ignoreUndefined = true;
595-
}
596-
597591
// Is the bypassDocumentValidation options specific
598592
if (bulkOperation.s.bypassDocumentValidation === true) {
599593
finalOptions.bypassDocumentValidation = true;
@@ -870,6 +864,8 @@ interface BulkOperationPrivate {
870864
topology: Topology;
871865
// Options
872866
options: BulkWriteOptions;
867+
// BSON options
868+
bsonOptions: BSONSerializeOptions;
873869
// Document used to build a bulk operation
874870
currentOp?: Document;
875871
// Executed
@@ -985,6 +981,8 @@ export abstract class BulkOperationBase {
985981
topology,
986982
// Options
987983
options: finalOptions,
984+
// BSON options
985+
bsonOptions: resolveBSONOptions(options, collection),
988986
// Current operation
989987
currentOp,
990988
// Executed
@@ -1166,6 +1164,10 @@ export abstract class BulkOperationBase {
11661164
);
11671165
}
11681166

1167+
get bsonOptions(): BSONSerializeOptions {
1168+
return this.s.bsonOptions;
1169+
}
1170+
11691171
/** An internal helper method. Do not invoke directly. Will be going away in the future */
11701172
execute(
11711173
_writeConcern?: WriteConcern,

src/collection.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,24 +1288,12 @@ export class Collection implements OperationParent {
12881288

12891289
/** Initiate an Out of order batch write operation. All operations will be buffered into insert/update/remove commands executed out of order. */
12901290
initializeUnorderedBulkOp(options?: BulkWriteOptions): any {
1291-
options = options || {};
1292-
// Give function's options precedence over session options.
1293-
if (options.ignoreUndefined == null) {
1294-
options.ignoreUndefined = this.bsonOptions.ignoreUndefined;
1295-
}
1296-
1297-
return new UnorderedBulkOperation(this, options);
1291+
return new UnorderedBulkOperation(this, options ?? {});
12981292
}
12991293

13001294
/** Initiate an In order bulk write operation. Operations will be serially executed in the order they are added, creating a new operation for each switch in types. */
13011295
initializeOrderedBulkOp(options?: BulkWriteOptions): any {
1302-
options = options || {};
1303-
// Give function's options precedence over session's options.
1304-
if (options.ignoreUndefined == null) {
1305-
options.ignoreUndefined = this.bsonOptions.ignoreUndefined;
1306-
}
1307-
1308-
return new OrderedBulkOperation(this, options);
1296+
return new OrderedBulkOperation(this, options ?? {});
13091297
}
13101298

13111299
/** Get the db scoped logger */

test/functional/bulk.test.js

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
'use strict';
2-
const test = require('./shared').assert,
3-
setupDatabase = require('./shared').setupDatabase,
4-
expect = require('chai').expect;
5-
6-
const MongoError = require('../../src/error').MongoError;
7-
const ignoreNsNotFound = require('./shared').ignoreNsNotFound;
2+
const { withClient, setupDatabase, ignoreNsNotFound } = require('./shared');
3+
const test = require('./shared').assert;
4+
const { expect } = require('chai');
5+
const { MongoError } = require('../../src/error');
6+
const { Long } = require('../../src');
87

98
describe('Bulk', function () {
109
before(function () {
@@ -158,6 +157,108 @@ describe('Bulk', function () {
158157
}
159158
});
160159

160+
it('should inherit promote long false from db during unordered bulk operation', function () {
161+
const client = this.configuration.newClient(this.configuration.writeConcernMax(), {
162+
promoteLongs: true
163+
});
164+
165+
return withClient.call(this, client, (client, done) => {
166+
const db = client.db('shouldInheritPromoteLongFalseFromDb1', { promoteLongs: false });
167+
const coll = db.collection('test');
168+
169+
const batch = coll.initializeUnorderedBulkOp();
170+
batch.insert({ a: Long.fromNumber(10) });
171+
batch.execute((err, result) => {
172+
expect(err).to.not.exist;
173+
expect(result).to.exist;
174+
175+
coll.findOne((err, item) => {
176+
expect(err).to.not.exist;
177+
expect(item.a).to.not.be.a('number');
178+
expect(item.a).to.have.property('_bsontype');
179+
expect(item.a._bsontype).to.be.equal('Long');
180+
181+
done();
182+
});
183+
});
184+
});
185+
});
186+
187+
it(
188+
'should inherit promote long false from collection during unordered bulk operation',
189+
withClient(function (client, done) {
190+
const db = client.db('shouldInheritPromoteLongFalseFromColl1', { promoteLongs: true });
191+
const coll = db.collection('test', { promoteLongs: false });
192+
193+
const batch = coll.initializeUnorderedBulkOp();
194+
batch.insert({ a: Long.fromNumber(10) });
195+
batch.execute((err, result) => {
196+
expect(err).to.not.exist;
197+
expect(result).to.exist;
198+
199+
coll.findOne((err, item) => {
200+
expect(err).to.not.exist;
201+
expect(item.a).to.not.be.a('number');
202+
expect(item.a).to.have.property('_bsontype');
203+
expect(item.a._bsontype).to.be.equal('Long');
204+
205+
done();
206+
});
207+
});
208+
})
209+
);
210+
211+
it('should inherit promote long false from db during ordered bulk operation', function () {
212+
const client = this.configuration.newClient(this.configuration.writeConcernMax(), {
213+
promoteLongs: true
214+
});
215+
216+
return withClient.call(this, client, (client, done) => {
217+
const db = client.db('shouldInheritPromoteLongFalseFromDb2', { promoteLongs: false });
218+
const coll = db.collection('test');
219+
220+
const batch = coll.initializeOrderedBulkOp();
221+
batch.insert({ a: Long.fromNumber(10) });
222+
batch.execute((err, result) => {
223+
expect(err).to.not.exist;
224+
expect(result).to.exist;
225+
226+
coll.findOne((err, item) => {
227+
expect(err).to.not.exist;
228+
expect(item.a).to.not.be.a('number');
229+
expect(item.a).to.have.property('_bsontype');
230+
expect(item.a._bsontype).to.be.equal('Long');
231+
232+
done();
233+
});
234+
});
235+
});
236+
});
237+
238+
it(
239+
'should inherit promote long false from collection during ordered bulk operation',
240+
withClient(function (client, done) {
241+
const db = client.db('shouldInheritPromoteLongFalseFromColl2', { promoteLongs: true });
242+
const coll = db.collection('test', { promoteLongs: false });
243+
244+
const batch = coll.initializeOrderedBulkOp();
245+
batch.insert({ a: Long.fromNumber(10) });
246+
batch.execute((err, result) => {
247+
expect(err).to.not.exist;
248+
expect(result).to.exist;
249+
250+
coll.findOne((err, item) => {
251+
expect(err).to.not.exist;
252+
expect(item.a).to.not.be.a('number');
253+
expect(item.a).to.have.property('_bsontype');
254+
expect(item.a._bsontype).to.be.equal('Long');
255+
256+
done();
257+
});
258+
});
259+
})
260+
);
261+
161262
it('should correctly handle ordered multiple batch api write command errors', {
162263
metadata: {
163264
requires: { topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] }

0 commit comments

Comments
 (0)