123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- 'use strict';
- const Aspect = require('./operation').Aspect;
- const OperationBase = require('./operation').OperationBase;
- const ReadPreference = require('../core').ReadPreference;
- const ReadConcern = require('../read_concern');
- const WriteConcern = require('../write_concern');
- const maxWireVersion = require('../core/utils').maxWireVersion;
- const decorateWithExplain = require('../utils').decorateWithExplain;
- const commandSupportsReadConcern = require('../core/sessions').commandSupportsReadConcern;
- const MongoError = require('../core/error').MongoError;
- const extractCommand = require('../command_utils').extractCommand;
- const SUPPORTS_WRITE_CONCERN_AND_COLLATION = 5;
- class CommandOperationV2 extends OperationBase {
- constructor(parent, options, operationOptions) {
- super(options);
- this.ns = parent.s.namespace.withCollection('$cmd');
- const propertyProvider = this.hasAspect(Aspect.NO_INHERIT_OPTIONS) ? undefined : parent;
- this.readPreference = this.hasAspect(Aspect.WRITE_OPERATION)
- ? ReadPreference.primary
- : ReadPreference.resolve(propertyProvider, this.options);
- this.readConcern = resolveReadConcern(propertyProvider, this.options);
- this.writeConcern = resolveWriteConcern(propertyProvider, this.options);
- if (operationOptions && typeof operationOptions.fullResponse === 'boolean') {
- this.fullResponse = true;
- }
- // TODO: A lot of our code depends on having the read preference in the options. This should
- // go away, but also requires massive test rewrites.
- this.options.readPreference = this.readPreference;
- // TODO(NODE-2056): make logger another "inheritable" property
- if (parent.s.logger) {
- this.logger = parent.s.logger;
- } else if (parent.s.db && parent.s.db.logger) {
- this.logger = parent.s.db.logger;
- }
- }
- executeCommand(server, cmd, callback) {
- // TODO: consider making this a non-enumerable property
- this.server = server;
- const options = this.options;
- const serverWireVersion = maxWireVersion(server);
- const inTransaction = this.session && this.session.inTransaction();
- if (this.readConcern && commandSupportsReadConcern(cmd) && !inTransaction) {
- Object.assign(cmd, { readConcern: this.readConcern });
- }
- if (options.collation && serverWireVersion < SUPPORTS_WRITE_CONCERN_AND_COLLATION) {
- callback(
- new MongoError(
- `Server ${server.name}, which reports wire version ${serverWireVersion}, does not support collation`
- )
- );
- return;
- }
- if (serverWireVersion >= SUPPORTS_WRITE_CONCERN_AND_COLLATION) {
- if (this.writeConcern && this.hasAspect(Aspect.WRITE_OPERATION)) {
- Object.assign(cmd, { writeConcern: this.writeConcern });
- }
- if (options.collation && typeof options.collation === 'object') {
- Object.assign(cmd, { collation: options.collation });
- }
- }
- if (typeof options.maxTimeMS === 'number') {
- cmd.maxTimeMS = options.maxTimeMS;
- }
- if (typeof options.comment === 'string') {
- cmd.comment = options.comment;
- }
- if (this.hasAspect(Aspect.EXPLAINABLE) && this.explain) {
- if (serverWireVersion < 6 && cmd.aggregate) {
- // Prior to 3.6, with aggregate, verbosity is ignored, and we must pass in "explain: true"
- cmd.explain = true;
- } else {
- cmd = decorateWithExplain(cmd, this.explain);
- }
- }
- if (this.logger && this.logger.isDebug()) {
- const extractedCommand = extractCommand(cmd);
- this.logger.debug(
- `executing command ${JSON.stringify(
- extractedCommand.shouldRedact ? `${extractedCommand.name} details REDACTED` : cmd
- )} against ${this.ns}`
- );
- }
- server.command(this.ns.toString(), cmd, this.options, (err, result) => {
- if (err) {
- callback(err, null);
- return;
- }
- if (this.fullResponse) {
- callback(null, result);
- return;
- }
- callback(null, result.result);
- });
- }
- }
- function resolveWriteConcern(parent, options) {
- return WriteConcern.fromOptions(options) || (parent && parent.writeConcern);
- }
- function resolveReadConcern(parent, options) {
- return ReadConcern.fromOptions(options) || (parent && parent.readConcern);
- }
- module.exports = CommandOperationV2;
|