1+ import type { Callback , Document } from '.' ;
2+ import { MongoError } from './error' ;
3+ import { CommandOperation , CommandOperationOptions , OperationParent } from './operations/command' ;
14import type { Server } from './sdam/server' ;
25import { maxWireVersion } from './utils' ;
36
4- export const SUPPORTS_EXPLAIN_WITH_REMOVE = 3 ;
5- export const SUPPORTS_EXPLAIN_WITH_UPDATE = 3 ;
6- export const SUPPORTS_EXPLAIN_WITH_DISTINCT = 3.2 ;
7- export const SUPPORTS_EXPLAIN_WITH_FIND_AND_MODIFY = 3.2 ;
8- export const SUPPORTS_EXPLAIN_WITH_MAP_REDUCE = 4.4 ;
7+ const SUPPORTS_EXPLAIN_WITH_REMOVE = 3 ;
8+ const SUPPORTS_EXPLAIN_WITH_UPDATE = 3 ;
9+ const SUPPORTS_EXPLAIN_WITH_DISTINCT = 3.2 ;
10+ const SUPPORTS_EXPLAIN_WITH_FIND_AND_MODIFY = 3.2 ;
11+ const SUPPORTS_EXPLAIN_WITH_MAP_REDUCE = 4.4 ;
12+
13+ /** @internal */
14+ export abstract class ExplainableCommand <
15+ T extends ExplainOptions = ExplainOptions ,
16+ TResult = Document
17+ > extends CommandOperation < T , TResult > {
18+ explain ?: Explain ;
19+
20+ constructor ( parent ?: OperationParent , options ?: T ) {
21+ super ( parent , options ) ;
22+ this . explain = Explain . fromOptions ( options ) ;
23+ }
24+
25+ get canRetryWrite ( ) : boolean {
26+ return this . explain === undefined ;
27+ }
28+
29+ executeCommand ( server : Server , cmd : Document , callback : Callback ) : void {
30+ if ( this . explain ) {
31+ if ( ! Explain . explainSupportedOnCmd ( server , cmd ) ) {
32+ callback ( new MongoError ( `server ${ server . name } does not support explain on this command` ) ) ;
33+ return ;
34+ }
35+
36+ cmd . explain = this . explain ;
37+ }
38+ super . executeCommand ( server , cmd , callback ) ;
39+ }
40+ }
941
1042/** @public */
11- export interface ExplainOptions {
43+ export interface ExplainOptions extends CommandOperationOptions {
1244 explain ?: VerbosityLike ;
1345}
1446
47+ /** @public */
1548export enum Verbosity {
1649 queryPlanner = 'queryPlanner' ,
1750 queryPlannerExtended = 'queryPlannerExtended' ,
@@ -22,6 +55,7 @@ export enum Verbosity {
2255/** @public */
2356export type VerbosityLike = Verbosity | boolean ;
2457
58+ /** @internal */
2559export class Explain {
2660 explain : Verbosity ;
2761
@@ -51,16 +85,43 @@ export class Explain {
5185 */
5286 static explainSupported ( server : Server , op : string ) : boolean {
5387 const wireVersion = maxWireVersion ( server ) ;
54- if (
88+ return (
5589 ( op === 'remove' && wireVersion >= SUPPORTS_EXPLAIN_WITH_REMOVE ) ||
5690 ( op === 'update' && wireVersion >= SUPPORTS_EXPLAIN_WITH_UPDATE ) ||
5791 ( op === 'distinct' && wireVersion >= SUPPORTS_EXPLAIN_WITH_DISTINCT ) ||
5892 ( op === 'findAndModify' && wireVersion >= SUPPORTS_EXPLAIN_WITH_FIND_AND_MODIFY ) ||
5993 ( op === 'mapReduce' && wireVersion >= SUPPORTS_EXPLAIN_WITH_MAP_REDUCE )
60- ) {
61- return true ;
62- }
94+ ) ;
95+ }
6396
64- return false ;
97+ static explainSupportedOnCmd ( server : Server , cmd : Document ) : boolean {
98+ const wireVersion = maxWireVersion ( server ) ;
99+ return (
100+ ( cmd . remove && wireVersion >= SUPPORTS_EXPLAIN_WITH_REMOVE ) ||
101+ ( cmd . update && wireVersion >= SUPPORTS_EXPLAIN_WITH_UPDATE ) ||
102+ ( cmd . distinct && wireVersion >= SUPPORTS_EXPLAIN_WITH_DISTINCT ) ||
103+ ( cmd . findAndModify && wireVersion >= SUPPORTS_EXPLAIN_WITH_FIND_AND_MODIFY ) ||
104+ ( cmd . mapReduce && wireVersion >= SUPPORTS_EXPLAIN_WITH_MAP_REDUCE )
105+ ) ;
65106 }
66107}
108+
109+ /**
110+ * Applies an explain to a given command.
111+ * @internal
112+ *
113+ * @param command - the command on which to apply the read concern
114+ * @param options - the options containing the explain verbosity
115+ */
116+ export function decorateWithExplain ( command : Document , options : ExplainOptions ) : Document {
117+ const explain = Explain . fromOptions ( options ) ;
118+ if ( explain === undefined ) return command ;
119+
120+ // A command may not have an explain field on it
121+ if ( command . explain !== undefined ) {
122+ delete command . explain ;
123+ }
124+
125+ command = { explain : command , verbosity : explain . explain } ;
126+ return command ;
127+ }
0 commit comments