1
1
use std:: time:: Duration ;
2
2
3
- use bson:: { Bson , Document } ;
3
+ use bson:: { Bson , Document , RawDocumentBuf } ;
4
4
5
5
use crate :: {
6
6
client:: session:: TransactionState ,
@@ -40,7 +40,27 @@ impl Database {
40
40
pub fn run_command ( & self , command : Document ) -> RunCommand {
41
41
RunCommand {
42
42
db : self ,
43
- command,
43
+ command : RawDocumentBuf :: from_document ( & command) ,
44
+ options : None ,
45
+ session : None ,
46
+ }
47
+ }
48
+
49
+ /// Runs a database-level command.
50
+ ///
51
+ /// Note that no inspection is done on `doc`, so the command will not use the database's default
52
+ /// read concern or write concern. If specific read concern or write concern is desired, it must
53
+ /// be specified manually.
54
+ /// Please note that run_raw_command doesn't validate WriteConcerns passed into the body of the
55
+ /// command document.
56
+ ///
57
+ /// `await` will return d[`Result<Document>`].
58
+ #[ deeplink]
59
+ #[ options_doc( run_command) ]
60
+ pub fn run_raw_command ( & self , command : RawDocumentBuf ) -> RunCommand {
61
+ RunCommand {
62
+ db : self ,
63
+ command : Ok ( command) ,
44
64
options : None ,
45
65
session : None ,
46
66
}
@@ -55,7 +75,22 @@ impl Database {
55
75
pub fn run_cursor_command ( & self , command : Document ) -> RunCursorCommand {
56
76
RunCursorCommand {
57
77
db : self ,
58
- command,
78
+ command : RawDocumentBuf :: from_document ( & command) ,
79
+ options : None ,
80
+ session : ImplicitSession ,
81
+ }
82
+ }
83
+
84
+ /// Runs a database-level command and returns a cursor to the response.
85
+ ///
86
+ /// `await` will return d[`Result<Cursor<Document>>`] or a
87
+ /// d[`Result<SessionCursor<Document>>`] if a [`ClientSession`] is provided.
88
+ #[ deeplink]
89
+ #[ options_doc( run_cursor_command) ]
90
+ pub fn run_raw_cursor_command ( & self , command : RawDocumentBuf ) -> RunCursorCommand {
91
+ RunCursorCommand {
92
+ db : self ,
93
+ command : Ok ( command) ,
59
94
options : None ,
60
95
session : ImplicitSession ,
61
96
}
@@ -79,6 +114,21 @@ impl crate::sync::Database {
79
114
self . async_database . run_command ( command)
80
115
}
81
116
117
+ /// Runs a database-level command.
118
+ ///
119
+ /// Note that no inspection is done on `doc`, so the command will not use the database's default
120
+ /// read concern or write concern. If specific read concern or write concern is desired, it must
121
+ /// be specified manually.
122
+ /// Please note that run_raw_command doesn't validate WriteConcerns passed into the body of the
123
+ /// command document.
124
+ ///
125
+ /// [`run`](RunCommand::run) will return d[`Result<Document>`].
126
+ #[ deeplink]
127
+ #[ options_doc( run_command, sync) ]
128
+ pub fn run_raw_command ( & self , command : RawDocumentBuf ) -> RunCommand {
129
+ self . async_database . run_raw_command ( command)
130
+ }
131
+
82
132
/// Runs a database-level command and returns a cursor to the response.
83
133
///
84
134
/// [`run`](RunCursorCommand::run) will return d[`Result<crate::sync::Cursor<Document>>`] or a
@@ -88,13 +138,23 @@ impl crate::sync::Database {
88
138
pub fn run_cursor_command ( & self , command : Document ) -> RunCursorCommand {
89
139
self . async_database . run_cursor_command ( command)
90
140
}
141
+
142
+ /// Runs a database-level command and returns a cursor to the response.
143
+ ///
144
+ /// [`run`](RunCursorCommand::run) will return d[`Result<crate::sync::Cursor<Document>>`] or a
145
+ /// d[`Result<crate::sync::SessionCursor<Document>>`] if a [`ClientSession`] is provided.
146
+ #[ deeplink]
147
+ #[ options_doc( run_cursor_command, sync) ]
148
+ pub fn run_raw_cursor_command ( & self , command : RawDocumentBuf ) -> RunCursorCommand {
149
+ self . async_database . run_raw_cursor_command ( command)
150
+ }
91
151
}
92
152
93
153
/// Run a database-level command. Create with [`Database::run_command`].
94
154
#[ must_use]
95
155
pub struct RunCommand < ' a > {
96
156
db : & ' a Database ,
97
- command : Document ,
157
+ command : bson :: raw :: Result < RawDocumentBuf > ,
98
158
options : Option < RunCommandOptions > ,
99
159
session : Option < & ' a mut ClientSession > ,
100
160
}
@@ -115,10 +175,11 @@ impl<'a> Action for RunCommand<'a> {
115
175
116
176
async fn execute ( self ) -> Result < Document > {
117
177
let mut selection_criteria = self . options . and_then ( |o| o. selection_criteria ) ;
178
+ let command = self . command ?;
118
179
if let Some ( session) = & self . session {
119
180
match session. transaction . state {
120
181
TransactionState :: Starting | TransactionState :: InProgress => {
121
- if self . command . contains_key ( "readConcern" ) {
182
+ if command. get ( "readConcern" ) . is_ok_and ( |rc| rc . is_some ( ) ) {
122
183
return Err ( ErrorKind :: InvalidArgument {
123
184
message : "Cannot set read concern after starting a transaction" . into ( ) ,
124
185
}
@@ -139,12 +200,8 @@ impl<'a> Action for RunCommand<'a> {
139
200
}
140
201
}
141
202
142
- let operation = run_command:: RunCommand :: new (
143
- self . db . name ( ) . into ( ) ,
144
- self . command ,
145
- selection_criteria,
146
- None ,
147
- ) ?;
203
+ let operation =
204
+ run_command:: RunCommand :: new ( self . db . name ( ) . into ( ) , command, selection_criteria, None ) ;
148
205
self . db
149
206
. client ( )
150
207
. execute_operation ( operation, self . session )
@@ -157,7 +214,7 @@ impl<'a> Action for RunCommand<'a> {
157
214
#[ must_use]
158
215
pub struct RunCursorCommand < ' a , Session = ImplicitSession > {
159
216
db : & ' a Database ,
160
- command : Document ,
217
+ command : bson :: raw :: Result < RawDocumentBuf > ,
161
218
options : Option < RunCursorCommandOptions > ,
162
219
session : Session ,
163
220
}
@@ -192,10 +249,10 @@ impl<'a> Action for RunCursorCommand<'a, ImplicitSession> {
192
249
. and_then ( |options| options. selection_criteria . clone ( ) ) ;
193
250
let rcc = run_command:: RunCommand :: new (
194
251
self . db . name ( ) . to_string ( ) ,
195
- self . command ,
252
+ self . command ? ,
196
253
selection_criteria,
197
254
None ,
198
- ) ? ;
255
+ ) ;
199
256
let rc_command = run_cursor_command:: RunCursorCommand :: new ( rcc, self . options ) ?;
200
257
let client = self . db . client ( ) ;
201
258
client. execute_cursor_operation ( rc_command) . await
@@ -218,10 +275,10 @@ impl<'a> Action for RunCursorCommand<'a, ExplicitSession<'a>> {
218
275
. and_then ( |options| options. selection_criteria . clone ( ) ) ;
219
276
let rcc = run_command:: RunCommand :: new (
220
277
self . db . name ( ) . to_string ( ) ,
221
- self . command ,
278
+ self . command ? ,
222
279
selection_criteria,
223
280
None ,
224
- ) ? ;
281
+ ) ;
225
282
let rc_command = run_cursor_command:: RunCursorCommand :: new ( rcc, self . options ) ?;
226
283
let client = self . db . client ( ) ;
227
284
client
0 commit comments