Skip to content

Commit 40d60bf

Browse files
committed
rm TransactionError
This was always a fairly clunky API. Its main upside was that type inference was able to figure out the error type in more cases than the current implementation does. It has much larger downsides though. The most common case is that you're just returning `diesel::result::Error` anyway, so this enum was just an annoyance. If you weren't returning that, you were probably returning an application specific error which has a variant for `diesel::result::Error`, and now also had to handle this additional type. It also turns out that [`TransactionError<Box<::std::error::Error>>` doesn't implement `::std::error::Error`](rust-lang/rust#39792). The new API might require explicitly stating the error type in a few more places (in particular `try!(conn.transaction(|| try!(query); Ok(()))); Ok(...)` stopped inferring), but I think that this will end up being more ergonomic for most uses.
1 parent ea6c55c commit 40d60bf

File tree

7 files changed

+40
-80
lines changed

7 files changed

+40
-80
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/
3131

3232
[now-0.11.0]: http://docs.diesel.rs/diesel/expression/dsl/struct.now.html
3333

34+
* [`Connection::transaction`][transaction-0.11.0] now returns your error
35+
directly instead of wrapping it in `TransactionError`. It requires that the
36+
error implement `From<diesel::result::Error>`
37+
38+
[transaction-0.11.0]: http://docs.diesel.rs/diesel/connection/trait.Connection.html#method.transaction
39+
40+
### Removed
41+
42+
* `result::TransactionError`
43+
* `result::TransactionResult`
44+
3445
## [0.10.1] - 2017-02-08
3546

3647
### Fixed

diesel/src/connection/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ pub trait Connection: SimpleConnection + Sized {
3434
/// function returns an `Err`,
3535
/// [`TransactionError::UserReturnedError`](../result/enum.TransactionError.html#variant.UserReturnedError)
3636
/// will be returned wrapping that value.
37-
fn transaction<T, E, F>(&self, f: F) -> TransactionResult<T, E> where
37+
fn transaction<T, E, F>(&self, f: F) -> Result<T, E> where
3838
F: FnOnce() -> Result<T, E>,
39+
E: From<Error>,
3940
{
4041
let transaction_manager = self.transaction_manager();
4142
try!(transaction_manager.begin_transaction(self));
@@ -46,7 +47,7 @@ pub trait Connection: SimpleConnection + Sized {
4647
},
4748
Err(e) => {
4849
try!(transaction_manager.rollback_transaction(self));
49-
Err(TransactionError::UserReturnedError(e))
50+
Err(e)
5051
},
5152
}
5253
}
@@ -67,7 +68,7 @@ pub trait Connection: SimpleConnection + Sized {
6768
let mut user_result = None;
6869
let _ = self.transaction::<(), _, _>(|| {
6970
user_result = f().ok();
70-
Err(())
71+
Err(Error::RollbackTransaction)
7172
});
7273
user_result.expect("Transaction did not succeed")
7374
}

diesel/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ pub mod prelude {
123123
pub use insertable::Insertable;
124124
pub use query_dsl::*;
125125
pub use query_source::{QuerySource, Queryable, Table, Column, JoinTo};
126-
pub use result::{QueryResult, TransactionError, TransactionResult, ConnectionError, ConnectionResult, OptionalExtension};
126+
pub use result::{QueryResult, ConnectionError, ConnectionResult, OptionalExtension};
127127
}
128128

129129
pub use prelude::*;

diesel/src/migrations/migration_error.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use result::{self, TransactionError};
1+
use result;
22

33
use std::convert::From;
44
use std::{fmt, io};
@@ -99,13 +99,3 @@ impl From<io::Error> for RunMigrationsError {
9999
RunMigrationsError::MigrationError(e.into())
100100
}
101101
}
102-
103-
impl From<TransactionError<RunMigrationsError>> for RunMigrationsError {
104-
fn from(e: TransactionError<RunMigrationsError>) -> Self {
105-
use result::TransactionError::*;
106-
match e {
107-
CouldntCreateTransaction(e) => RunMigrationsError::from(e),
108-
UserReturnedError(e) => e,
109-
}
110-
}
111-
}

diesel/src/migrations/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,20 +227,19 @@ fn run_migration<Conn>(conn: &Conn, migration: &Migration, output: &mut Write)
227227
try!(migration.run(conn));
228228
try!(conn.insert_new_migration(migration.version()));
229229
Ok(())
230-
}).map_err(|e| e.into())
230+
})
231231
}
232232

233233
fn revert_migration<Conn: Connection>(conn: &Conn, migration: Box<Migration>, output: &mut Write)
234234
-> Result<(), RunMigrationsError>
235235
{
236-
try!(conn.transaction(|| {
236+
conn.transaction(|| {
237237
try!(writeln!(output, "Rolling back migration {}", migration.version()));
238238
try!(migration.revert(conn));
239239
let target = __diesel_schema_migrations.filter(version.eq(migration.version()));
240240
try!(::delete(target).execute(conn));
241241
Ok(())
242-
}));
243-
Ok(())
242+
})
244243
}
245244

246245
/// Returns the directory containing migrations. Will look at for

diesel/src/result.rs

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ pub enum Error {
1515
QueryBuilderError(Box<StdError+Send+Sync>),
1616
DeserializationError(Box<StdError+Send+Sync>),
1717
SerializationError(Box<StdError+Send+Sync>),
18+
/// You can return this variant inside of a transaction when you want to
19+
/// roll it back, but have no actual error to return. Diesel will never
20+
/// return this variant unless you gave it to us, and it can be safely
21+
/// ignored in error handling.
22+
RollbackTransaction,
1823
#[doc(hidden)]
1924
__Nonexhaustive,
2025
}
@@ -68,15 +73,8 @@ pub enum ConnectionError {
6873
__Nonexhaustive, // Match against _ instead, more variants may be added in the future
6974
}
7075

71-
#[derive(Debug, PartialEq)]
72-
pub enum TransactionError<E> {
73-
CouldntCreateTransaction(Error),
74-
UserReturnedError(E),
75-
}
76-
7776
pub type QueryResult<T> = Result<T, Error>;
7877
pub type ConnectionResult<T> = Result<T, ConnectionError>;
79-
pub type TransactionResult<T, E> = Result<T, TransactionError<E>>;
8078

8179
pub trait OptionalExtension<T> {
8280
fn optional(self) -> Result<Option<T>, Error>;
@@ -104,21 +102,6 @@ impl From<NulError> for Error {
104102
}
105103
}
106104

107-
impl<E> From<Error> for TransactionError<E> {
108-
fn from(e: Error) -> Self {
109-
TransactionError::CouldntCreateTransaction(e)
110-
}
111-
}
112-
113-
impl From<TransactionError<Error>> for Error {
114-
fn from(e: TransactionError<Error>) -> Self {
115-
match e {
116-
TransactionError::CouldntCreateTransaction(e) |
117-
TransactionError::UserReturnedError(e) => e,
118-
}
119-
}
120-
}
121-
122105
impl Display for Error {
123106
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124107
match *self {
@@ -128,6 +111,7 @@ impl Display for Error {
128111
Error::QueryBuilderError(ref e) => e.fmt(f),
129112
Error::DeserializationError(ref e) => e.fmt(f),
130113
Error::SerializationError(ref e) => e.fmt(f),
114+
Error::RollbackTransaction => write!(f, "{}", self.description()),
131115
Error::__Nonexhaustive => unreachable!(),
132116
}
133117
}
@@ -142,6 +126,7 @@ impl StdError for Error {
142126
Error::QueryBuilderError(ref e) => e.description(),
143127
Error::DeserializationError(ref e) => e.description(),
144128
Error::SerializationError(ref e) => e.description(),
129+
Error::RollbackTransaction => "The current transaction was aborted",
145130
Error::__Nonexhaustive => unreachable!(),
146131
}
147132
}
@@ -169,24 +154,6 @@ impl StdError for ConnectionError {
169154
}
170155
}
171156

172-
impl<E: Display> Display for TransactionError<E> {
173-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174-
match *self {
175-
TransactionError::CouldntCreateTransaction(ref e) => e.fmt(f),
176-
TransactionError::UserReturnedError(ref e) => e.fmt(f),
177-
}
178-
}
179-
}
180-
181-
impl<E: StdError> StdError for TransactionError<E> {
182-
fn description(&self) -> &str {
183-
match *self {
184-
TransactionError::CouldntCreateTransaction(ref e) => e.description(),
185-
TransactionError::UserReturnedError(ref e) => e.description(),
186-
}
187-
}
188-
}
189-
190157
impl PartialEq for Error {
191158
fn eq(&self, other: &Error) -> bool {
192159
match (self, other) {

diesel_tests/tests/transactions.rs

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
use schema::*;
22
use diesel::*;
3-
4-
macro_rules! try_no_coerce {
5-
($e:expr) => ({
6-
match $e {
7-
Ok(e) => e,
8-
Err(e) => return Err(e),
9-
}
10-
})
11-
}
3+
use diesel::result::Error;
124

135
#[test]
146
#[cfg(not(feature = "sqlite"))] // FIXME: This test is only valid when operating on a file and not :memory:
@@ -19,10 +11,10 @@ fn transaction_executes_fn_in_a_sql_transaction() {
1911
setup_test_table(&conn1, test_name);
2012
let get_count = |conn| count_test_table(conn, test_name);
2113

22-
conn1.transaction(|| {
14+
conn1.transaction::<_, Error, _>(|| {
2315
assert_eq!(0, get_count(&conn1));
2416
assert_eq!(0, get_count(&conn2));
25-
try_no_coerce!(conn1.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name)));
17+
try!(conn1.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name)));
2618
assert_eq!(1, get_count(&conn1));
2719
assert_eq!(0, get_count(&conn2));
2820
Ok(())
@@ -38,7 +30,7 @@ fn transaction_executes_fn_in_a_sql_transaction() {
3830
fn transaction_returns_the_returned_value() {
3931
let conn1 = connection_without_transaction();
4032

41-
assert_eq!(Ok(1), conn1.transaction::<_, (), _>(|| Ok(1)));
33+
assert_eq!(Ok(1), conn1.transaction::<_, Error, _>(|| Ok(1)));
4234
}
4335

4436
#[test]
@@ -48,9 +40,9 @@ fn transaction_is_rolled_back_when_returned_an_error() {
4840
setup_test_table(&connection, test_name);
4941
let get_count = || count_test_table(&connection, test_name);
5042

51-
let _ = connection.transaction::<(), (), _>(|| {
43+
let _ = connection.transaction::<(), _, _>(|| {
5244
connection.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name)).unwrap();
53-
Err(())
45+
Err(Error::RollbackTransaction)
5446
});
5547
assert_eq!(0, get_count());
5648

@@ -64,22 +56,22 @@ fn transactions_can_be_nested() {
6456
setup_test_table(&connection, test_name);
6557
let get_count = || count_test_table(&connection, test_name);
6658

67-
let _ = connection.transaction::<(), (), _>(|| {
59+
let _ = connection.transaction::<(), _, _>(|| {
6860
connection.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name)).unwrap();
6961
assert_eq!(1, get_count());
70-
let _ = connection.transaction::<(), (), _>(|| {
62+
let _ = connection.transaction::<(), _, _>(|| {
7163
connection.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name)).unwrap();
7264
assert_eq!(2, get_count());
73-
Err(())
65+
Err(Error::RollbackTransaction)
7466
});
7567
assert_eq!(1, get_count());
76-
let _ = connection.transaction::<(), (), _>(|| {
68+
let _ = connection.transaction::<(), Error, _>(|| {
7769
connection.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name)).unwrap();
7870
assert_eq!(2, get_count());
7971
Ok(())
8072
});
8173
assert_eq!(2, get_count());
82-
Err(())
74+
Err(Error::RollbackTransaction)
8375
});
8476
assert_eq!(0, get_count());
8577

@@ -92,8 +84,8 @@ fn test_transaction_always_rolls_back() {
9284
let test_name = "test_transaction_always_rolls_back";
9385
setup_test_table(&connection, test_name);
9486

95-
let result = connection.test_transaction(|| {
96-
try_no_coerce!(connection.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name)));
87+
let result = connection.test_transaction::<_, Error, _>(|| {
88+
try!(connection.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name)));
9789
assert_eq!(1, count_test_table(&connection, test_name));
9890
Ok("success")
9991
});

0 commit comments

Comments
 (0)