Skip to content

Commit 269c176

Browse files
committed
Move transaction to its own module
1 parent 2a29aae commit 269c176

File tree

3 files changed

+176
-141
lines changed

3 files changed

+176
-141
lines changed

src/lib.rs

Lines changed: 14 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ use std::time::Duration;
7171
#[cfg(feature = "unix_socket")]
7272
use std::path::PathBuf;
7373

74+
// FIXME remove in 0.12
75+
pub use transaction::Transaction;
76+
7477
use error::{Error, ConnectError, SqlState, DbError};
7578
use io::{StreamWrapper, NegotiateSsl};
7679
use message::BackendMessage::*;
@@ -93,10 +96,11 @@ mod url;
9396
mod util;
9497
pub mod error;
9598
pub mod io;
99+
pub mod notification;
96100
pub mod rows;
97101
pub mod stmt;
102+
pub mod transaction;
98103
pub mod types;
99-
pub mod notification;
100104

101105
const TYPEINFO_QUERY: &'static str = "__typeinfo";
102106
const TYPEINFO_ENUM_QUERY: &'static str = "__typeinfo_enum";
@@ -1172,12 +1176,7 @@ impl Connection {
11721176
"`transaction` must be called on the active transaction");
11731177
try!(conn.quick_query("BEGIN"));
11741178
conn.trans_depth += 1;
1175-
Ok(Transaction {
1176-
conn: self,
1177-
commit: Cell::new(false),
1178-
depth: 1,
1179-
finished: false,
1180-
})
1179+
Ok(Transaction::new(self, 1))
11811180
}
11821181

11831182
/// Creates a new prepared statement.
@@ -1343,136 +1342,6 @@ impl Connection {
13431342
}
13441343
}
13451344

1346-
/// Represents a transaction on a database connection.
1347-
///
1348-
/// The transaction will roll back by default.
1349-
pub struct Transaction<'conn> {
1350-
conn: &'conn Connection,
1351-
depth: u32,
1352-
commit: Cell<bool>,
1353-
finished: bool,
1354-
}
1355-
1356-
impl<'a> fmt::Debug for Transaction<'a> {
1357-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1358-
fmt.debug_struct("Transaction")
1359-
.field("commit", &self.commit.get())
1360-
.field("depth", &self.depth)
1361-
.finish()
1362-
}
1363-
}
1364-
1365-
impl<'conn> Drop for Transaction<'conn> {
1366-
fn drop(&mut self) {
1367-
if !self.finished {
1368-
let _ = self.finish_inner();
1369-
}
1370-
}
1371-
}
1372-
1373-
impl<'conn> Transaction<'conn> {
1374-
fn finish_inner(&mut self) -> Result<()> {
1375-
let mut conn = self.conn.conn.borrow_mut();
1376-
debug_assert!(self.depth == conn.trans_depth);
1377-
let query = match (self.commit.get(), self.depth != 1) {
1378-
(false, true) => "ROLLBACK TO sp",
1379-
(false, false) => "ROLLBACK",
1380-
(true, true) => "RELEASE sp",
1381-
(true, false) => "COMMIT",
1382-
};
1383-
conn.trans_depth -= 1;
1384-
conn.quick_query(query).map(|_| ())
1385-
}
1386-
1387-
/// Like `Connection::prepare`.
1388-
pub fn prepare(&self, query: &str) -> Result<Statement<'conn>> {
1389-
self.conn.prepare(query)
1390-
}
1391-
1392-
/// Like `Connection::prepare_cached`.
1393-
///
1394-
/// Note that the statement will be cached for the duration of the
1395-
/// connection, not just the duration of this transaction.
1396-
pub fn prepare_cached(&self, query: &str) -> Result<Statement<'conn>> {
1397-
self.conn.prepare_cached(query)
1398-
}
1399-
1400-
/// Like `Connection::execute`.
1401-
pub fn execute(&self, query: &str, params: &[&ToSql]) -> Result<u64> {
1402-
self.conn.execute(query, params)
1403-
}
1404-
1405-
/// Like `Connection::query`.
1406-
pub fn query<'a>(&'a self, query: &str, params: &[&ToSql]) -> Result<Rows<'a>> {
1407-
self.conn.query(query, params)
1408-
}
1409-
1410-
/// Like `Connection::batch_execute`.
1411-
pub fn batch_execute(&self, query: &str) -> Result<()> {
1412-
self.conn.batch_execute(query)
1413-
}
1414-
1415-
/// Like `Connection::transaction`.
1416-
///
1417-
/// # Panics
1418-
///
1419-
/// Panics if there is an active nested transaction.
1420-
pub fn transaction<'a>(&'a self) -> Result<Transaction<'a>> {
1421-
let mut conn = self.conn.conn.borrow_mut();
1422-
check_desync!(conn);
1423-
assert!(conn.trans_depth == self.depth,
1424-
"`transaction` may only be called on the active transaction");
1425-
try!(conn.quick_query("SAVEPOINT sp"));
1426-
conn.trans_depth += 1;
1427-
Ok(Transaction {
1428-
conn: self.conn,
1429-
commit: Cell::new(false),
1430-
depth: self.depth + 1,
1431-
finished: false,
1432-
})
1433-
}
1434-
1435-
/// Returns a reference to the `Transaction`'s `Connection`.
1436-
pub fn connection(&self) -> &'conn Connection {
1437-
self.conn
1438-
}
1439-
1440-
/// Like `Connection::is_active`.
1441-
pub fn is_active(&self) -> bool {
1442-
self.conn.conn.borrow().trans_depth == self.depth
1443-
}
1444-
1445-
/// Determines if the transaction is currently set to commit or roll back.
1446-
pub fn will_commit(&self) -> bool {
1447-
self.commit.get()
1448-
}
1449-
1450-
/// Sets the transaction to commit at its completion.
1451-
pub fn set_commit(&self) {
1452-
self.commit.set(true);
1453-
}
1454-
1455-
/// Sets the transaction to roll back at its completion.
1456-
pub fn set_rollback(&self) {
1457-
self.commit.set(false);
1458-
}
1459-
1460-
/// A convenience method which consumes and commits a transaction.
1461-
pub fn commit(self) -> Result<()> {
1462-
self.set_commit();
1463-
self.finish()
1464-
}
1465-
1466-
/// Consumes the transaction, commiting or rolling it back as appropriate.
1467-
///
1468-
/// Functionally equivalent to the `Drop` implementation of `Transaction`
1469-
/// except that it returns any error to the caller.
1470-
pub fn finish(mut self) -> Result<()> {
1471-
self.finished = true;
1472-
self.finish_inner()
1473-
}
1474-
}
1475-
14761345
/// A trait allowing abstraction over connections and transactions
14771346
pub trait GenericConnection {
14781347
/// Like `Connection::execute`.
@@ -1614,3 +1483,11 @@ trait WrongTypeNew {
16141483
trait FieldNew {
16151484
fn new(name: String, type_: Type) -> Field;
16161485
}
1486+
1487+
trait TransactionInternals<'conn> {
1488+
fn new(conn: &'conn Connection, depth: u32) -> Transaction<'conn>;
1489+
1490+
fn conn(&self) -> &'conn Connection;
1491+
1492+
fn depth(&self) -> u32;
1493+
}

src/stmt.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use message::BackendMessage::*;
1313
use message::WriteMessage;
1414
use util;
1515
use rows::{Rows, LazyRows};
16-
use {bad_response, Connection, Transaction, StatementInternals, Result, RowsNew};
17-
use {InnerConnection, SessionInfoNew, LazyRowsNew, DbErrorNew, ColumnNew, StatementInfo};
16+
use {bad_response, Connection, Transaction, StatementInternals, Result, RowsNew, InnerConnection,
17+
SessionInfoNew, LazyRowsNew, DbErrorNew, ColumnNew, StatementInfo, TransactionInternals};
1818

1919
/// A prepared statement.
2020
pub struct Statement<'conn> {
@@ -226,12 +226,12 @@ impl<'conn> Statement<'conn> {
226226
params: &[&ToSql],
227227
row_limit: i32)
228228
-> Result<LazyRows<'trans, 'stmt>> {
229-
assert!(self.conn as *const _ == trans.conn as *const _,
229+
assert!(self.conn as *const _ == trans.conn() as *const _,
230230
"the `Transaction` passed to `lazy_query` must be associated with the same \
231231
`Connection` as the `Statement`");
232232
let conn = self.conn.conn.borrow();
233233
check_desync!(conn);
234-
assert!(conn.trans_depth == trans.depth,
234+
assert!(conn.trans_depth == trans.depth(),
235235
"`lazy_query` must be passed the active transaction");
236236
drop(conn);
237237

src/transaction.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
//! Transactions
2+
3+
use std::cell::Cell;
4+
use std::fmt;
5+
6+
use {Result, Connection, TransactionInternals};
7+
use stmt::Statement;
8+
use rows::Rows;
9+
use types::ToSql;
10+
11+
/// A transaction on a database connection.
12+
///
13+
/// The transaction will roll back by default.
14+
pub struct Transaction<'conn> {
15+
conn: &'conn Connection,
16+
depth: u32,
17+
commit: Cell<bool>,
18+
finished: bool,
19+
}
20+
21+
impl<'a> fmt::Debug for Transaction<'a> {
22+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
23+
fmt.debug_struct("Transaction")
24+
.field("commit", &self.commit.get())
25+
.field("depth", &self.depth)
26+
.finish()
27+
}
28+
}
29+
30+
impl<'conn> Drop for Transaction<'conn> {
31+
fn drop(&mut self) {
32+
if !self.finished {
33+
let _ = self.finish_inner();
34+
}
35+
}
36+
}
37+
38+
impl<'conn> TransactionInternals<'conn> for Transaction<'conn> {
39+
fn new(conn: &'conn Connection, depth: u32) -> Transaction<'conn> {
40+
Transaction {
41+
conn: conn,
42+
depth: depth,
43+
commit: Cell::new(false),
44+
finished: false,
45+
}
46+
}
47+
48+
fn conn(&self) -> &'conn Connection {
49+
self.conn
50+
}
51+
52+
fn depth(&self) -> u32 {
53+
self.depth
54+
}
55+
}
56+
57+
impl<'conn> Transaction<'conn> {
58+
fn finish_inner(&mut self) -> Result<()> {
59+
let mut conn = self.conn.conn.borrow_mut();
60+
debug_assert!(self.depth == conn.trans_depth);
61+
let query = match (self.commit.get(), self.depth != 1) {
62+
(false, true) => "ROLLBACK TO sp",
63+
(false, false) => "ROLLBACK",
64+
(true, true) => "RELEASE sp",
65+
(true, false) => "COMMIT",
66+
};
67+
conn.trans_depth -= 1;
68+
conn.quick_query(query).map(|_| ())
69+
}
70+
71+
/// Like `Connection::prepare`.
72+
pub fn prepare(&self, query: &str) -> Result<Statement<'conn>> {
73+
self.conn.prepare(query)
74+
}
75+
76+
/// Like `Connection::prepare_cached`.
77+
///
78+
/// Note that the statement will be cached for the duration of the
79+
/// connection, not just the duration of this transaction.
80+
pub fn prepare_cached(&self, query: &str) -> Result<Statement<'conn>> {
81+
self.conn.prepare_cached(query)
82+
}
83+
84+
/// Like `Connection::execute`.
85+
pub fn execute(&self, query: &str, params: &[&ToSql]) -> Result<u64> {
86+
self.conn.execute(query, params)
87+
}
88+
89+
/// Like `Connection::query`.
90+
pub fn query<'a>(&'a self, query: &str, params: &[&ToSql]) -> Result<Rows<'a>> {
91+
self.conn.query(query, params)
92+
}
93+
94+
/// Like `Connection::batch_execute`.
95+
pub fn batch_execute(&self, query: &str) -> Result<()> {
96+
self.conn.batch_execute(query)
97+
}
98+
99+
/// Like `Connection::transaction`.
100+
///
101+
/// # Panics
102+
///
103+
/// Panics if there is an active nested transaction.
104+
pub fn transaction<'a>(&'a self) -> Result<Transaction<'a>> {
105+
let mut conn = self.conn.conn.borrow_mut();
106+
check_desync!(conn);
107+
assert!(conn.trans_depth == self.depth,
108+
"`transaction` may only be called on the active transaction");
109+
try!(conn.quick_query("SAVEPOINT sp"));
110+
conn.trans_depth += 1;
111+
Ok(Transaction {
112+
conn: self.conn,
113+
commit: Cell::new(false),
114+
depth: self.depth + 1,
115+
finished: false,
116+
})
117+
}
118+
119+
/// Returns a reference to the `Transaction`'s `Connection`.
120+
pub fn connection(&self) -> &'conn Connection {
121+
self.conn
122+
}
123+
124+
/// Like `Connection::is_active`.
125+
pub fn is_active(&self) -> bool {
126+
self.conn.conn.borrow().trans_depth == self.depth
127+
}
128+
129+
/// Determines if the transaction is currently set to commit or roll back.
130+
pub fn will_commit(&self) -> bool {
131+
self.commit.get()
132+
}
133+
134+
/// Sets the transaction to commit at its completion.
135+
pub fn set_commit(&self) {
136+
self.commit.set(true);
137+
}
138+
139+
/// Sets the transaction to roll back at its completion.
140+
pub fn set_rollback(&self) {
141+
self.commit.set(false);
142+
}
143+
144+
/// A convenience method which consumes and commits a transaction.
145+
pub fn commit(self) -> Result<()> {
146+
self.set_commit();
147+
self.finish()
148+
}
149+
150+
/// Consumes the transaction, commiting or rolling it back as appropriate.
151+
///
152+
/// Functionally equivalent to the `Drop` implementation of `Transaction`
153+
/// except that it returns any error to the caller.
154+
pub fn finish(mut self) -> Result<()> {
155+
self.finished = true;
156+
self.finish_inner()
157+
}
158+
}

0 commit comments

Comments
 (0)