@@ -59,6 +59,7 @@ use debug_builders::DebugStruct;
5959use openssl:: crypto:: hash:: { self , Hasher } ;
6060use openssl:: ssl:: { SslContext , MaybeSslStream } ;
6161use serialize:: hex:: ToHex ;
62+ use std:: ascii:: AsciiExt ;
6263use std:: borrow:: { ToOwned , Cow } ;
6364use std:: cell:: { Cell , RefCell } ;
6465use std:: collections:: { VecDeque , HashMap } ;
@@ -399,6 +400,60 @@ pub fn cancel_query<T>(params: T, ssl: &SslMode, data: CancelData)
399400 Ok ( ( ) )
400401}
401402
403+ /// An enumeration of transaction isolation levels.
404+ ///
405+ /// See the (Postgres documentation)[http://www.postgresql.org/docs/9.4/static/transaction-iso.html]
406+ /// for full details on the semantics of each level.
407+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
408+ pub enum IsolationLevel {
409+ /// The "read uncommitted" level.
410+ ///
411+ /// In current versions of Postgres, this behaves identically to
412+ /// `ReadCommitted`.
413+ ReadUncommitted ,
414+ /// The "read committed" level.
415+ ///
416+ /// This is the default isolation level in Postgres.
417+ ReadCommitted ,
418+ /// The "repeatable read" level.
419+ RepeatableRead ,
420+ /// The "serializable" level.
421+ Serializable ,
422+ }
423+
424+ impl IsolationLevel {
425+ fn to_set_query ( & self ) -> & ' static str {
426+ match * self {
427+ IsolationLevel :: ReadUncommitted => {
428+ "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"
429+ }
430+ IsolationLevel :: ReadCommitted => {
431+ "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ COMMITTED"
432+ }
433+ IsolationLevel :: RepeatableRead => {
434+ "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL REPEATABLE READ"
435+ }
436+ IsolationLevel :: Serializable => {
437+ "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE"
438+ }
439+ }
440+ }
441+
442+ fn parse ( raw : & str ) -> Result < IsolationLevel > {
443+ if raw. eq_ignore_ascii_case ( "READ UNCOMMITTED" ) {
444+ Ok ( IsolationLevel :: ReadUncommitted )
445+ } else if raw. eq_ignore_ascii_case ( "READ COMMITTED" ) {
446+ Ok ( IsolationLevel :: ReadCommitted )
447+ } else if raw. eq_ignore_ascii_case ( "REPEATABLE READ" ) {
448+ Ok ( IsolationLevel :: RepeatableRead )
449+ } else if raw. eq_ignore_ascii_case ( "SERIALIZABLE" ) {
450+ Ok ( IsolationLevel :: Serializable )
451+ } else {
452+ Err ( Error :: BadResponse )
453+ }
454+ }
455+ }
456+
402457#[ derive( Clone ) ]
403458struct CachedStatement {
404459 name : String ,
@@ -1062,6 +1117,23 @@ impl Connection {
10621117 } )
10631118 }
10641119
1120+ /// Sets the isolation level which will be used for future transactions.
1121+ ///
1122+ /// ## Note
1123+ ///
1124+ /// This will not change the behavior of an active transaction.
1125+ pub fn set_transaction_isolation ( & self , level : IsolationLevel ) -> Result < ( ) > {
1126+ self . batch_execute ( level. to_set_query ( ) )
1127+ }
1128+
1129+ /// Returns the isolation level which will be used for future transactions.
1130+ pub fn get_transaction_isolation ( & self ) -> Result < IsolationLevel > {
1131+ let mut conn = self . conn . borrow_mut ( ) ;
1132+ check_desync ! ( conn) ;
1133+ let result = try!( conn. quick_query ( "SHOW TRANSACTION ISOLATION LEVEL" ) ) ;
1134+ IsolationLevel :: parse ( result[ 0 ] [ 0 ] . as_ref ( ) . unwrap ( ) )
1135+ }
1136+
10651137 /// A convenience function for queries that are only run once.
10661138 ///
10671139 /// If an error is returned, it could have come from either the preparation
0 commit comments