@@ -151,6 +151,7 @@ impl Config {
151151pub struct Transaction < ' conn > {
152152 conn : & ' conn Connection ,
153153 depth : u32 ,
154+ savepoint_name : Option < String > ,
154155 commit : Cell < bool > ,
155156 finished : bool ,
156157}
@@ -177,6 +178,7 @@ impl<'conn> TransactionInternals<'conn> for Transaction<'conn> {
177178 Transaction {
178179 conn : conn,
179180 depth : depth,
181+ savepoint_name : None ,
180182 commit : Cell :: new ( false ) ,
181183 finished : false ,
182184 }
@@ -195,14 +197,17 @@ impl<'conn> Transaction<'conn> {
195197 fn finish_inner ( & mut self ) -> Result < ( ) > {
196198 let mut conn = self . conn . conn . borrow_mut ( ) ;
197199 debug_assert ! ( self . depth == conn. trans_depth) ;
198- let query = match ( self . commit . get ( ) , self . depth != 1 ) {
199- ( false , true ) => "ROLLBACK TO sp" ,
200- ( false , false ) => "ROLLBACK" ,
201- ( true , true ) => "RELEASE sp" ,
202- ( true , false ) => "COMMIT" ,
203- } ;
204200 conn. trans_depth -= 1 ;
205- conn. quick_query ( query) . map ( |_| ( ) )
201+ match ( self . commit . get ( ) , & self . savepoint_name ) {
202+ ( false , & Some ( ref savepoint_name) ) => {
203+ conn. quick_query ( & format ! ( "ROLLBACK TO {}" , savepoint_name) )
204+ }
205+ ( false , & None ) => conn. quick_query ( "ROLLBACK" ) ,
206+ ( true , & Some ( ref savepoint_name) ) => {
207+ conn. quick_query ( & format ! ( "RELEASE {}" , savepoint_name) )
208+ }
209+ ( true , & None ) => conn. quick_query ( "COMMIT" ) ,
210+ } . map ( |_| ( ) )
206211 }
207212
208213 /// Like `Connection::prepare`.
@@ -233,22 +238,34 @@ impl<'conn> Transaction<'conn> {
233238 self . conn . batch_execute ( query)
234239 }
235240
236- /// Like `Connection::transaction`.
241+ /// Like `Connection::transaction`, but creates a nested transaction via
242+ /// a savepoint.
237243 ///
238244 /// # Panics
239245 ///
240246 /// Panics if there is an active nested transaction.
241247 pub fn transaction < ' a > ( & ' a self ) -> Result < Transaction < ' a > > {
248+ self . savepoint ( "sp" )
249+ }
250+
251+ /// Like `Connection::transaction`, but creates a nested transaction via
252+ /// a savepoint with the specified name.
253+ ///
254+ /// # Panics
255+ ///
256+ /// Panics if there is an active nested transaction.
257+ pub fn savepoint < ' a > ( & ' a self , name : & str ) -> Result < Transaction < ' a > > {
242258 let mut conn = self . conn . conn . borrow_mut ( ) ;
243259 check_desync ! ( conn) ;
244260 assert ! ( conn. trans_depth == self . depth,
245- "`transaction ` may only be called on the active transaction" ) ;
246- try!( conn. quick_query ( "SAVEPOINT sp" ) ) ;
261+ "`savepoint ` may only be called on the active transaction" ) ;
262+ try!( conn. quick_query ( & format ! ( "SAVEPOINT {}" , name ) ) ) ;
247263 conn. trans_depth += 1 ;
248264 Ok ( Transaction {
249265 conn : self . conn ,
250- commit : Cell :: new ( false ) ,
251266 depth : self . depth + 1 ,
267+ savepoint_name : Some ( name. to_owned ( ) ) ,
268+ commit : Cell :: new ( false ) ,
252269 finished : false ,
253270 } )
254271 }
0 commit comments