@@ -59,6 +59,7 @@ use debug_builders::DebugStruct;
59
59
use openssl:: crypto:: hash:: { self , Hasher } ;
60
60
use openssl:: ssl:: { SslContext , MaybeSslStream } ;
61
61
use serialize:: hex:: ToHex ;
62
+ use std:: ascii:: AsciiExt ;
62
63
use std:: borrow:: { ToOwned , Cow } ;
63
64
use std:: cell:: { Cell , RefCell } ;
64
65
use std:: collections:: { VecDeque , HashMap } ;
@@ -399,6 +400,60 @@ pub fn cancel_query<T>(params: T, ssl: &SslMode, data: CancelData)
399
400
Ok ( ( ) )
400
401
}
401
402
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
+
402
457
#[ derive( Clone ) ]
403
458
struct CachedStatement {
404
459
name : String ,
@@ -1062,6 +1117,23 @@ impl Connection {
1062
1117
} )
1063
1118
}
1064
1119
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
+
1065
1137
/// A convenience function for queries that are only run once.
1066
1138
///
1067
1139
/// If an error is returned, it could have come from either the preparation
0 commit comments