Finish up transaction config

This commit is contained in:
Steven Fackler 2016-02-24 22:29:09 -08:00
parent 6f59fb5b35
commit 5b80b251a6
3 changed files with 65 additions and 13 deletions

View File

@ -1162,11 +1162,18 @@ impl Connection {
/// trans.commit().unwrap();
/// ```
pub fn transaction<'a>(&'a self) -> Result<Transaction<'a>> {
self.transaction_with(&transaction::Config::new())
}
/// Begins a new transaction with the specified configuration.
pub fn transaction_with<'a>(&'a self, config: &transaction::Config) -> Result<Transaction<'a>> {
let mut conn = self.conn.borrow_mut();
check_desync!(conn);
assert!(conn.trans_depth == 0,
"`transaction` must be called on the active transaction");
try!(conn.quick_query("BEGIN"));
let mut query = "BEGIN".to_owned();
config.build_command(&mut query);
try!(conn.quick_query(&query));
conn.trans_depth += 1;
Ok(Transaction::new(self, 1))
}
@ -1230,17 +1237,14 @@ impl Connection {
IsolationLevel::parse(result[0][0].as_ref().unwrap())
}
/// Sets the isolation level which will be used for future transactions.
/// # Deprecated
///
/// This is a simple wrapper around `SET TRANSACTION ISOLATION LEVEL ...`.
///
/// # Note
///
/// This will not change the behavior of an active transaction.
/// Use `Connection::set_transaction_config` instead.
pub fn set_transaction_isolation(&self, level: IsolationLevel) -> Result<()> {
self.set_transaction_config(transaction::Config::new().isolation_level(level))
}
/// Sets the configuration that will be used for future transactions.
pub fn set_transaction_config(&self, config: &transaction::Config) -> Result<()> {
let mut command = "SET SESSION CHARACTERISTICS AS TRANSACTION".to_owned();
config.build_command(&mut command);

View File

@ -8,6 +8,7 @@ use stmt::Statement;
use rows::Rows;
use types::ToSql;
/// Configuration of a transaction.
#[derive(Debug)]
pub struct Config {
isolation_level: Option<IsolationLevel>,
@ -51,6 +52,7 @@ impl ConfigInternals for Config {
}
impl Config {
/// Creates a new `Config` with no configuration overrides.
pub fn new() -> Config {
Config {
isolation_level: None,
@ -59,16 +61,27 @@ impl Config {
}
}
/// Sets the isolation level of the configuration.
pub fn isolation_level(&mut self, isolation_level: IsolationLevel) -> &mut Config {
self.isolation_level = Some(isolation_level);
self
}
/// Sets the read-only property of a transaction.
///
/// If enabled, a transaction will be unable to modify any persistent
/// database state.
pub fn read_only(&mut self, read_only: bool) -> &mut Config {
self.read_only = Some(read_only);
self
}
/// Sets the deferrable property of a transaction.
///
/// If enabled in a read only, serializable transaction, the transaction may
/// block when created, after which it will run without the normal overhead
/// of a serializable transaction and will not be forced to roll back due
/// to serialization failures.
pub fn deferrable(&mut self, deferrable: bool) -> &mut Config {
self.deferrable = Some(deferrable);
self
@ -193,6 +206,13 @@ impl<'conn> Transaction<'conn> {
self.conn.conn.borrow().trans_depth == self.depth
}
/// Alters the configuration of the active transaction.
pub fn set_config(&self, config: &Config) -> Result<()> {
let mut command = "SET TRANSACTION".to_owned();
config.build_command(&mut command);
self.batch_execute(&command)
}
/// Determines if the transaction is currently set to commit or roll back.
pub fn will_commit(&self) -> bool {
self.commit.get()

View File

@ -13,12 +13,8 @@ use std::io;
use std::io::prelude::*;
use std::time::Duration;
use postgres::{HandleNotice,
Connection,
GenericConnection,
SslMode,
IntoConnectParams,
IsolationLevel};
use postgres::{HandleNotice, Connection, GenericConnection, SslMode, IntoConnectParams,
IsolationLevel, transaction};
use postgres::error::{Error, ConnectError, DbError};
use postgres::types::{Oid, Type, Kind, WrongType};
use postgres::error::SqlState::{SyntaxError,
@ -1020,3 +1016,35 @@ fn test_conn_query() {
.collect::<Vec<i32>>();
assert_eq!(ids, [1, 2, 3]);
}
#[test]
fn transaction_config() {
let conn = Connection::connect("postgres://postgres@localhost", SslMode::None).unwrap();
let mut config = transaction::Config::new();
config.isolation_level(IsolationLevel::Serializable)
.read_only(true)
.deferrable(true);
conn.set_transaction_config(&config).unwrap();
}
#[test]
fn transaction_with() {
let conn = Connection::connect("postgres://postgres@localhost", SslMode::None).unwrap();
let mut config = transaction::Config::new();
config.isolation_level(IsolationLevel::Serializable)
.read_only(true)
.deferrable(true);
conn.transaction_with(&config).unwrap().finish().unwrap();
}
#[test]
fn transaction_set_config() {
let conn = Connection::connect("postgres://postgres@localhost", SslMode::None).unwrap();
let trans = conn.transaction().unwrap();
let mut config = transaction::Config::new();
config.isolation_level(IsolationLevel::Serializable)
.read_only(true)
.deferrable(true);
trans.set_config(&config).unwrap();
trans.finish().unwrap();
}