@@ -20,6 +20,7 @@ use tokio::io::{AsyncRead, AsyncWrite};
2020/// transaction. Transactions can be nested, with inner transactions implemented via safepoints.
2121pub struct Transaction < ' a > {
2222 client : & ' a mut Client ,
23+ depth : u32 ,
2324 done : bool ,
2425}
2526
@@ -30,7 +31,12 @@ impl<'a> Drop for Transaction<'a> {
3031 }
3132
3233 let mut buf = vec ! [ ] ;
33- frontend:: query ( "ROLLBACK" , & mut buf) . unwrap ( ) ;
34+ let query = if self . depth == 0 {
35+ "ROLLBACK" . to_string ( )
36+ } else {
37+ format ! ( "ROLLBACK TO sp{}" , self . depth)
38+ } ;
39+ frontend:: query ( & query, & mut buf) . unwrap ( ) ;
3440 let _ = self
3541 . client
3642 . inner ( )
@@ -42,22 +48,33 @@ impl<'a> Transaction<'a> {
4248 pub ( crate ) fn new ( client : & ' a mut Client ) -> Transaction < ' a > {
4349 Transaction {
4450 client,
51+ depth : 0 ,
4552 done : false ,
4653 }
4754 }
4855
4956 /// Consumes the transaction, committing all changes made within it.
5057 pub async fn commit ( mut self ) -> Result < ( ) , Error > {
5158 self . done = true ;
52- self . client . batch_execute ( "COMMIT" ) . await
59+ let query = if self . depth == 0 {
60+ "COMMIT" . to_string ( )
61+ } else {
62+ format ! ( "RELEASE sp{}" , self . depth)
63+ } ;
64+ self . client . batch_execute ( & query) . await
5365 }
5466
5567 /// Rolls the transaction back, discarding all changes made within it.
5668 ///
5769 /// This is equivalent to `Transaction`'s `Drop` implementation, but provides any error encountered to the caller.
5870 pub async fn rollback ( mut self ) -> Result < ( ) , Error > {
5971 self . done = true ;
60- self . client . batch_execute ( "ROLLBACK" ) . await
72+ let query = if self . depth == 0 {
73+ "ROLLBACK" . to_string ( )
74+ } else {
75+ format ! ( "ROLLBACK TO sp{}" , self . depth)
76+ } ;
77+ self . client . batch_execute ( & query) . await
6178 }
6279
6380 /// Like `Client::prepare`.
@@ -227,4 +244,17 @@ impl<'a> Transaction<'a> {
227244 {
228245 self . client . cancel_query_raw ( stream, tls)
229246 }
247+
248+ /// Like `Client::transaction`.
249+ pub async fn transaction ( & mut self ) -> Result < Transaction < ' _ > , Error > {
250+ let depth = self . depth + 1 ;
251+ let query = format ! ( "SAVEPOINT sp{}" , depth) ;
252+ self . batch_execute ( & query) . await ?;
253+
254+ Ok ( Transaction {
255+ client : self . client ,
256+ depth,
257+ done : false ,
258+ } )
259+ }
230260}
0 commit comments