@@ -6,6 +6,9 @@ module Database.PostgreSQL.Query.Functions
6
6
-- * Transactions
7
7
, pgWithTransaction
8
8
, pgWithSavepoint
9
+ , pgWithTransactionMode
10
+ , pgWithTransactionModeRetry
11
+ , pgWithTransactionSerializable
9
12
-- * Work with entities
10
13
, pgInsertEntity
11
14
, pgInsertManyEntities
@@ -49,12 +52,14 @@ import Database.PostgreSQL.Query.Types
49
52
( FN , HasPostgres (.. ), TransactionSafe ,
50
53
ToMarkedRow (.. ), MarkedRow (.. ), mrToBuilder )
51
54
import Database.PostgreSQL.Simple
52
- ( ToRow , FromRow , execute_ , query_ ,
53
- withTransaction , withSavepoint )
55
+ ( ToRow , FromRow , execute_ , query_ , )
54
56
import Database.PostgreSQL.Simple.FromField
55
57
( FromField )
58
+ import Database.PostgreSQL.Simple.Internal
59
+ ( SqlError )
56
60
import Database.PostgreSQL.Simple.ToField
57
61
( ToField )
62
+ import Database.PostgreSQL.Simple.Transaction
58
63
import Database.PostgreSQL.Simple.Types
59
64
( Query (.. ), Only (.. ), (:.) (.. ) )
60
65
@@ -76,6 +81,48 @@ pgWithSavepoint action = withPGConnection $ \con -> do
76
81
control $ \ runInIO -> do
77
82
withSavepoint con $ runInIO action
78
83
84
+ -- | Wrapper for 'withTransactionMode': Execute an action inside a SQL
85
+ -- transaction with a given transaction mode.
86
+ pgWithTransactionMode :: (HasPostgres m , MonadBaseControl IO m , TransactionSafe m )
87
+ => TransactionMode
88
+ -> m a
89
+ -> m a
90
+ pgWithTransactionMode tmode ma = withPGConnection $ \ con -> do
91
+ control $ \ runInIO -> do
92
+ withTransactionMode tmode con $ runInIO ma
93
+
94
+ -- | Wrapper for 'withTransactionModeRetry': Like 'pgWithTransactionMode',
95
+ -- but also takes a custom callback to determine if a transaction
96
+ -- should be retried if an SqlError occurs. If the callback returns
97
+ -- True, then the transaction will be retried. If the callback returns
98
+ -- False, or an exception other than an SqlError occurs then the
99
+ -- transaction will be rolled back and the exception rethrown.
100
+ pgWithTransactionModeRetry :: (HasPostgres m , MonadBaseControl IO m , TransactionSafe m )
101
+ => TransactionMode
102
+ -> (SqlError -> Bool )
103
+ -> m a
104
+ -> m a
105
+ pgWithTransactionModeRetry tmode epred ma = withPGConnection $ \ con -> do
106
+ control $ \ runInIO -> do
107
+ withTransactionModeRetry tmode epred con $ runInIO ma
108
+
109
+ -- | Wrapper for 'withTransactionSerializable': Execute an action
110
+ -- inside of a 'Serializable' transaction. If a serialization failure
111
+ -- occurs, roll back the transaction and try again. Be warned that
112
+ -- this may execute the IO action multiple times.
113
+ --
114
+ -- A Serializable transaction creates the illusion that your program
115
+ -- has exclusive access to the database. This means that, even in a
116
+ -- concurrent setting, you can perform queries in sequence without
117
+ -- having to worry about what might happen between one statement and
118
+ -- the next.
119
+ pgWithTransactionSerializable :: (HasPostgres m , MonadBaseControl IO m , TransactionSafe m )
120
+ => m a
121
+ -> m a
122
+ pgWithTransactionSerializable ma = withPGConnection $ \ con -> do
123
+ control $ \ runInIO -> do
124
+ withTransactionSerializable con $ runInIO ma
125
+
79
126
{- | Execute query generated by 'SqlBuilder'. Typical use case:
80
127
81
128
@
0 commit comments