You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							126 lines
						
					
					
						
							4.2 KiB
						
					
					
				
			
		
		
	
	
							126 lines
						
					
					
						
							4.2 KiB
						
					
					
				| '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;
 |