@@ -9,6 +9,7 @@ use crate::describe::Describe;
9
9
use crate :: executor:: { Execute , Executor , RefExecutor } ;
10
10
use crate :: runtime:: spawn;
11
11
12
+ /// Represents a database transaction.
12
13
// Transaction<PoolConnection<PgConnection>>
13
14
// Transaction<PgConnection>
14
15
pub struct Transaction < T >
@@ -38,10 +39,14 @@ where
38
39
} )
39
40
}
40
41
41
- pub async fn begin ( mut self ) -> crate :: Result < Transaction < T > > {
42
- Transaction :: new ( self . depth , self . inner . take ( ) . expect ( ERR_FINALIZED ) ) . await
42
+ /// Creates a new save point in the current transaction and returns
43
+ /// a new `Transaction` object to manage its scope.
44
+ pub async fn begin ( self ) -> crate :: Result < Transaction < Transaction < T > > > {
45
+ Transaction :: new ( self . depth , self ) . await
43
46
}
44
47
48
+ /// Commits the current transaction or save point.
49
+ /// Returns the inner connection or transaction.
45
50
pub async fn commit ( mut self ) -> crate :: Result < T > {
46
51
let mut inner = self . inner . take ( ) . expect ( ERR_FINALIZED ) ;
47
52
let depth = self . depth ;
57
62
Ok ( inner)
58
63
}
59
64
65
+ /// Rollback the current transaction or save point.
66
+ /// Returns the inner connection or transaction.
60
67
pub async fn rollback ( mut self ) -> crate :: Result < T > {
61
68
let mut inner = self . inner . take ( ) . expect ( ERR_FINALIZED ) ;
62
69
let depth = self . depth ;
@@ -95,15 +102,49 @@ where
95
102
}
96
103
}
97
104
98
- impl < ' c , DB , T > Executor for & ' c mut Transaction < T >
105
+ impl < T > Connection for Transaction < T >
106
+ where
107
+ T : Connection ,
108
+ {
109
+ // Close is equivalent to
110
+ fn close ( mut self ) -> BoxFuture < ' static , crate :: Result < ( ) > > {
111
+ Box :: pin ( async move {
112
+ let mut inner = self . inner . take ( ) . expect ( ERR_FINALIZED ) ;
113
+
114
+ if self . depth == 1 {
115
+ // This is the root transaction, call rollback
116
+ let res = inner. execute ( "ROLLBACK" ) . await ;
117
+
118
+ // No matter the result of the above, call close
119
+ let _ = inner. close ( ) . await ;
120
+
121
+ // Now raise the error if there was one
122
+ res?;
123
+ } else {
124
+ // This is not the root transaction, forward to a nested
125
+ // transaction (to eventually call rollback)
126
+ inner. close ( ) . await ?
127
+ }
128
+
129
+ Ok ( ( ) )
130
+ } )
131
+ }
132
+
133
+ #[ inline]
134
+ fn ping ( & mut self ) -> BoxFuture < ' _ , crate :: Result < ( ) > > {
135
+ self . deref_mut ( ) . ping ( )
136
+ }
137
+ }
138
+
139
+ impl < DB , T > Executor for Transaction < T >
99
140
where
100
141
DB : Database ,
101
142
T : Connection < Database = DB > ,
102
143
{
103
144
type Database = T :: Database ;
104
145
105
- fn execute < ' e , ' q : ' e , ' t : ' e , E : ' e > (
106
- & ' t mut self ,
146
+ fn execute < ' e , ' q : ' e , ' c : ' e , E : ' e > (
147
+ & ' c mut self ,
107
148
query : E ,
108
149
) -> BoxFuture < ' e , crate :: Result < u64 > >
109
150
where
@@ -112,7 +153,7 @@ where
112
153
( * * self ) . execute ( query)
113
154
}
114
155
115
- fn fetch < ' q , ' e , E > ( & ' e mut self , query : E ) -> <Self :: Database as HasCursor < ' e , ' q > >:: Cursor
156
+ fn fetch < ' e , ' q , E > ( & ' e mut self , query : E ) -> <Self :: Database as HasCursor < ' e , ' q > >:: Cursor
116
157
where
117
158
E : Execute < ' q , Self :: Database > ,
118
159
{
@@ -151,16 +192,9 @@ where
151
192
{
152
193
fn drop ( & mut self ) {
153
194
if self . depth > 0 {
154
- if let Some ( mut inner) = self . inner . take ( ) {
195
+ if let Some ( inner) = self . inner . take ( ) {
155
196
spawn ( async move {
156
- let res = inner. execute ( "ROLLBACK" ) . await ;
157
-
158
- // If the rollback failed we need to close the inner connection
159
- if res. is_err ( ) {
160
- // This will explicitly forget the connection so it will not
161
- // return to the pool
162
- let _ = inner. close ( ) . await ;
163
- }
197
+ let _ = inner. close ( ) . await ;
164
198
} ) ;
165
199
}
166
200
}
0 commit comments