git.iko.soy/typeable/postgresql-simple
on master help sign in
Add support for read-only transactions
476112cLeon P Smith
src/Database/PostgreSQL/Simple.hs+45−20
@@ -69,8 +69,8 @@ module Database.PostgreSQL.Simple
69 , query
69 , query
70 , query_
70 , query_
71 -- * Queries that stream results
71 -- * Queries that stream results
72− , FetchQuantity(..)
73 , FoldOptions(..)
72 , FoldOptions(..)
73+ , FetchQuantity(..)
74 , defaultFoldOptions
74 , defaultFoldOptions
75 , fold
75 , fold
76 , foldWithOptions
76 , foldWithOptions
@@ -85,11 +85,13 @@ module Database.PostgreSQL.Simple
85-- , Base.insertID
85-- , Base.insertID
86 -- * Transaction handling
86 -- * Transaction handling
87 , withTransaction
87 , withTransaction
88− , withTransactionLevel
88+ , TransactionMode(..)
89 , IsolationLevel(..)
89 , IsolationLevel(..)
90+ , ReadWriteMode(..)
91+ , withTransactionMode
90-- , Base.autocommit
92-- , Base.autocommit
91 , begin
93 , begin
92− , beginLevel
94+ , beginMode
93 , commit
95 , commit
94 , rollback
96 , rollback
95 -- * Helper functions
97 -- * Helper functions
@@ -332,12 +334,14 @@ data FetchQuantity
332
334
333data FoldOptions
335data FoldOptions
334 = FoldOptions {
336 = FoldOptions {
335− fetchQuantity :: !FetchQuantity,
337+ fetchQuantity :: !FetchQuantity,
336− isolationLevel :: !IsolationLevel
338+ transactionMode :: !TransactionMode
337 }
339 }
338
340
339−defaultFoldOptions = FoldOptions { fetchQuantity = Automatic
341+defaultFoldOptions = FoldOptions {
340− , isolationLevel = ReadCommitted }
342+ fetchQuantity = Automatic,
343+ transactionMode = TransactionMode ReadCommitted ReadOnly
344+ }
341
345
342foldWithOptions :: ( QueryResults row, QueryParams params )
346foldWithOptions :: ( QueryResults row, QueryParams params )
343 => FoldOptions
347 => FoldOptions
@@ -382,7 +386,7 @@ doFold :: ( QueryResults row )
382doFold FoldOptions{..} conn _template q a f = do
386doFold FoldOptions{..} conn _template q a f = do
383 stat <- withConnection conn PQ.transactionStatus
387 stat <- withConnection conn PQ.transactionStatus
384 case stat of
388 case stat of
385− PQ.TransIdle -> withTransactionLevel isolationLevel conn go
389+ PQ.TransIdle -> withTransactionMode transactionMode conn go
386 PQ.TransInTrans -> go
390 PQ.TransInTrans -> go
387 PQ.TransActive -> fail "foldWithOpts FIXME: PQ.TransActive"
391 PQ.TransActive -> fail "foldWithOpts FIXME: PQ.TransActive"
388 -- This _shouldn't_ occur in the current incarnation of
392 -- This _shouldn't_ occur in the current incarnation of
@@ -484,6 +488,19 @@ data IsolationLevel
484 | Serializable
488 | Serializable
485 deriving (Show, Eq, Ord, Enum, Bounded)
489 deriving (Show, Eq, Ord, Enum, Bounded)
486
490
491+data ReadWriteMode
492+ = ReadWrite
493+ | ReadOnly
494+ deriving (Show, Eq, Ord, Enum, Bounded)
495+
496+data TransactionMode = TransactionMode {
497+ isolationLevel :: !IsolationLevel,
498+ readWriteMode :: !ReadWriteMode
499+ } deriving (Show, Eq, Ord)
500+
501+defaultTransactionMode :: TransactionMode
502+defaultTransactionMode = TransactionMode ReadCommitted ReadWrite
503+
487-- | Execute an action inside a SQL transaction.
504-- | Execute an action inside a SQL transaction.
488--
505--
489-- This function initiates a transaction with a \"@begin
506-- This function initiates a transaction with a \"@begin
@@ -495,18 +512,17 @@ data IsolationLevel
495-- PostgreSQL-related exception), the transaction will be rolled back using
512-- PostgreSQL-related exception), the transaction will be rolled back using
496-- 'rollback', then the exception will be rethrown.
513-- 'rollback', then the exception will be rethrown.
497withTransaction :: Connection -> IO a -> IO a
514withTransaction :: Connection -> IO a -> IO a
498−withTransaction = withTransactionLevel ReadCommitted
515+withTransaction = withTransactionMode defaultTransactionMode
499
516
500-- | Execute an action inside a SQL transaction with a given isolation level.
517-- | Execute an action inside a SQL transaction with a given isolation level.
501−withTransactionLevel :: IsolationLevel -> Connection -> IO a -> IO a
518+withTransactionMode :: TransactionMode -> Connection -> IO a -> IO a
502−withTransactionLevel isolationLevel conn act = do
519+withTransactionMode mode conn act = do
503− beginLevel isolationLevel conn
520+ beginMode mode conn
504 r <- act `onException` rollback conn
521 r <- act `onException` rollback conn
505 commit conn
522 commit conn
506 return r
523 return r
507
524
508-- | Rollback a transaction.
525-- | Rollback a transaction.
509−-- rollback :: (MonadCatchIO m,MonadIO m) => Connection -> m ()
510rollback :: Connection -> IO ()
526rollback :: Connection -> IO ()
511rollback conn = execute_ conn "ABORT" >> return ()
527rollback conn = execute_ conn "ABORT" >> return ()
512
528
@@ -516,15 +532,24 @@ commit conn = execute_ conn "COMMIT" >> return ()
516
532
517-- | Begin a transaction.
533-- | Begin a transaction.
518begin :: Connection -> IO ()
534begin :: Connection -> IO ()
519−begin = beginLevel ReadCommitted
535+begin = beginMode defaultTransactionMode
520
536
521-- | Begin a transaction with a given isolation level
537-- | Begin a transaction with a given isolation level
522−beginLevel :: IsolationLevel -> Connection -> IO ()
538+beginMode :: TransactionMode -> Connection -> IO ()
523−beginLevel isolationLevel conn = do
539+beginMode mode conn = do
524− execute_ conn $! case isolationLevel of
540+ execute_ conn $! case mode of
541+ TransactionMode ReadCommitted ReadWrite ->
542+ "BEGIN"
525− ReadCommitted -> "BEGIN"
543+ TransactionMode ReadCommitted ReadOnly ->
544+ "BEGIN READ ONLY"
545+ TransactionMode RepeatableRead ReadWrite ->
546+ "BEGIN ISOLATION LEVEL REPEATABLE READ"
547+ TransactionMode RepeatableRead ReadOnly ->
526− RepeatableRead -> "BEGIN ISOLATION LEVEL REPEATABLE READ"
548+ "BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY"
549+ TransactionMode Serializable ReadWrite ->
550+ "BEGIN ISOLATION LEVEL SERIALIZABLE"
551+ TransactionMode Serializable ReadOnly ->
527− Serializable -> "BEGIN ISOLATION LEVEL SERIALIZABLE"
552+ "BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY"
528 return ()
553 return ()
529
554
530fmtError :: String -> Query -> [Action] -> a
555fmtError :: String -> Query -> [Action] -> a