11use std:: time:: Duration ;
22
3- use bson:: { Bson , Document } ;
3+ use bson:: { Bson , Document , RawDocumentBuf } ;
44
55use crate :: {
66 client:: session:: TransactionState ,
@@ -40,7 +40,27 @@ impl Database {
4040 pub fn run_command ( & self , command : Document ) -> RunCommand {
4141 RunCommand {
4242 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) ,
4464 options : None ,
4565 session : None ,
4666 }
@@ -55,7 +75,22 @@ impl Database {
5575 pub fn run_cursor_command ( & self , command : Document ) -> RunCursorCommand {
5676 RunCursorCommand {
5777 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) ,
5994 options : None ,
6095 session : ImplicitSession ,
6196 }
@@ -79,6 +114,21 @@ impl crate::sync::Database {
79114 self . async_database . run_command ( command)
80115 }
81116
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+
82132 /// Runs a database-level command and returns a cursor to the response.
83133 ///
84134 /// [`run`](RunCursorCommand::run) will return d[`Result<crate::sync::Cursor<Document>>`] or a
@@ -88,13 +138,23 @@ impl crate::sync::Database {
88138 pub fn run_cursor_command ( & self , command : Document ) -> RunCursorCommand {
89139 self . async_database . run_cursor_command ( command)
90140 }
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+ }
91151}
92152
93153/// Run a database-level command. Create with [`Database::run_command`].
94154#[ must_use]
95155pub struct RunCommand < ' a > {
96156 db : & ' a Database ,
97- command : Document ,
157+ command : bson :: raw :: Result < RawDocumentBuf > ,
98158 options : Option < RunCommandOptions > ,
99159 session : Option < & ' a mut ClientSession > ,
100160}
@@ -115,10 +175,11 @@ impl<'a> Action for RunCommand<'a> {
115175
116176 async fn execute ( self ) -> Result < Document > {
117177 let mut selection_criteria = self . options . and_then ( |o| o. selection_criteria ) ;
178+ let command = self . command ?;
118179 if let Some ( session) = & self . session {
119180 match session. transaction . state {
120181 TransactionState :: Starting | TransactionState :: InProgress => {
121- if self . command . contains_key ( "readConcern" ) {
182+ if command. get ( "readConcern" ) . is_ok_and ( |rc| rc . is_some ( ) ) {
122183 return Err ( ErrorKind :: InvalidArgument {
123184 message : "Cannot set read concern after starting a transaction" . into ( ) ,
124185 }
@@ -139,12 +200,8 @@ impl<'a> Action for RunCommand<'a> {
139200 }
140201 }
141202
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 ) ;
148205 self . db
149206 . client ( )
150207 . execute_operation ( operation, self . session )
@@ -157,7 +214,7 @@ impl<'a> Action for RunCommand<'a> {
157214#[ must_use]
158215pub struct RunCursorCommand < ' a , Session = ImplicitSession > {
159216 db : & ' a Database ,
160- command : Document ,
217+ command : bson :: raw :: Result < RawDocumentBuf > ,
161218 options : Option < RunCursorCommandOptions > ,
162219 session : Session ,
163220}
@@ -192,10 +249,10 @@ impl<'a> Action for RunCursorCommand<'a, ImplicitSession> {
192249 . and_then ( |options| options. selection_criteria . clone ( ) ) ;
193250 let rcc = run_command:: RunCommand :: new (
194251 self . db . name ( ) . to_string ( ) ,
195- self . command ,
252+ self . command ? ,
196253 selection_criteria,
197254 None ,
198- ) ? ;
255+ ) ;
199256 let rc_command = run_cursor_command:: RunCursorCommand :: new ( rcc, self . options ) ?;
200257 let client = self . db . client ( ) ;
201258 client. execute_cursor_operation ( rc_command) . await
@@ -218,10 +275,10 @@ impl<'a> Action for RunCursorCommand<'a, ExplicitSession<'a>> {
218275 . and_then ( |options| options. selection_criteria . clone ( ) ) ;
219276 let rcc = run_command:: RunCommand :: new (
220277 self . db . name ( ) . to_string ( ) ,
221- self . command ,
278+ self . command ? ,
222279 selection_criteria,
223280 None ,
224- ) ? ;
281+ ) ;
225282 let rc_command = run_cursor_command:: RunCursorCommand :: new ( rcc, self . options ) ?;
226283 let client = self . db . client ( ) ;
227284 client
0 commit comments