Better transaction syntax

Closes #9
This commit is contained in:
Steven Fackler 2013-08-27 01:40:23 -04:00
parent 6afc2cac3f
commit afd7d8800d
2 changed files with 50 additions and 15 deletions

View File

@ -202,15 +202,18 @@ impl PostgresConnection {
})
}
pub fn in_transaction<T, E: ToStr>(&self, blk: &fn(&PostgresConnection)
-> Result<T, E>)
-> Result<T, E> {
pub fn in_transaction<T>(&self, blk: &fn(&PostgresTransaction) -> T)
-> T {
self.quick_query("BEGIN");
let trans = PostgresTransaction {
conn: self,
commit: Cell::new(true)
};
// If this fails, Postgres will rollback when the connection closes
let ret = blk(self);
let ret = blk(&trans);
if ret.is_ok() {
if trans.commit.take() {
self.quick_query("COMMIT");
} else {
self.quick_query("ROLLBACK");
@ -241,6 +244,38 @@ impl PostgresConnection {
}
}
pub struct PostgresTransaction<'self> {
priv conn: &'self PostgresConnection,
priv commit: Cell<bool>
}
impl<'self> PostgresTransaction<'self> {
pub fn prepare<'a>(&'a self, query: &str) -> PostgresStatement<'a> {
self.conn.prepare(query)
}
pub fn try_prepare<'a>(&'a self, query: &str)
-> Result<PostgresStatement<'a>, PostgresDbError> {
self.conn.try_prepare(query)
}
pub fn will_commit(&self) -> bool {
let commit = self.commit.take();
self.commit.put_back(commit);
commit
}
pub fn set_commit(&self) {
self.commit.take();
self.commit.put_back(true);
}
pub fn set_rollback(&self) {
self.commit.take();
self.commit.put_back(false);
}
}
pub struct PostgresStatement<'self> {
priv conn: &'self PostgresConnection,
priv name: ~str,

View File

@ -6,10 +6,10 @@ use postgres::{PostgresConnection, ToSql};
fn test_basic() {
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1:5432");
do conn.in_transaction |conn| {
conn.prepare("CREATE TABLE foo (id BIGINT PRIMARY KEY)").update([]);
do conn.in_transaction |trans| {
trans.prepare("CREATE TABLE foo (id BIGINT PRIMARY KEY)").update([]);
Err::<(), ()>(())
trans.set_rollback();
};
}
@ -23,16 +23,16 @@ fn test_prepare_err() {
fn test_query() {
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1:5432");
do conn.in_transaction |conn| {
conn.prepare("CREATE TABLE foo (id BIGINT PRIMARY KEY)").update([]);
conn.prepare("INSERT INTO foo (id) VALUES ($1), ($2)")
do conn.in_transaction |trans| {
trans.prepare("CREATE TABLE foo (id BIGINT PRIMARY KEY)").update([]);
trans.prepare("INSERT INTO foo (id) VALUES ($1), ($2)")
.update([&1 as &ToSql, &2 as &ToSql]);
let stmt = conn.prepare("SELECT * from foo ORDER BY id");
let stmt = trans.prepare("SELECT * from foo ORDER BY id");
let result = stmt.query([]);
assert_eq!(~[1, 2], result.iter().map(|row| { row[0] }).collect());
Err::<(), ()>(())
trans.set_rollback();
};
}
@ -40,7 +40,7 @@ fn test_query() {
fn test_nulls() {
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1:5432");
do conn.in_transaction |conn| {
do conn.in_transaction |trans| {
conn.prepare("CREATE TABLE foo (
id BIGINT PRIMARY KEY,
val VARCHAR
@ -54,7 +54,7 @@ fn test_nulls() {
assert_eq!(~[Some(~"foobar"), None],
result.iter().map(|row| { row[1] }).collect());
Err::<(), ()>(())
trans.set_rollback();
};
}