hasql-transaction 0.3.1 → 0.4.2
raw patch · 4 files changed
+47/−33 lines, 4 filesdep +mtldep ~hasqlPVP ok
version bump matches the API change (PVP)
Dependencies added: mtl
Dependency ranges changed: hasql
API changes (from Hackage documentation)
+ Hasql.Transaction: sql :: ByteString -> Transaction ()
- Hasql.Transaction: run :: Transaction a -> IsolationLevel -> Mode -> Connection -> IO (Either ResultsError a)
+ Hasql.Transaction: run :: Transaction a -> IsolationLevel -> Mode -> Session a
Files
- hasql-transaction.cabal +3/−2
- library/Hasql/Transaction.hs +29/−25
- library/Hasql/Transaction/Prelude.hs +9/−0
- library/Hasql/Transaction/Queries.hs +6/−6
hasql-transaction.cabal view
@@ -1,7 +1,7 @@ name: hasql-transaction version:- 0.3.1+ 0.4.2 category: Hasql, Database, PostgreSQL synopsis:@@ -47,7 +47,7 @@ exposed-modules: Hasql.Transaction build-depends:- hasql >= 0.15 && < 0.16,+ hasql >= 0.17 && < 0.20, -- database: postgresql-error-codes >= 1 && < 2, -- data:@@ -57,6 +57,7 @@ contravariant >= 1.3 && < 2, contravariant-extras >= 0.3 && < 0.4, either >= 4.4.1 && < 5,+ mtl >= 2 && < 3, transformers >= 0.3 && < 0.5, -- general: base-prelude >= 0.1.19 && < 0.2
library/Hasql/Transaction.hs view
@@ -6,13 +6,14 @@ -- * Transaction monad Transaction, run,+ sql, query, ) where import Hasql.Transaction.Prelude-import qualified Hasql.Connection as Connection import qualified Hasql.Query as Query+import qualified Hasql.Session as Session import qualified Hasql.Transaction.Queries as Queries import qualified PostgreSQL.ErrorCodes as ErrorCodes @@ -24,7 +25,7 @@ -- while automatically retrying the transaction in case of conflicts. -- Thus this abstraction closely reproduces the behaviour of 'STM'. newtype Transaction a =- Transaction (ReaderT (Connection.Connection, IORef Int) (EitherT Query.ResultsError IO) a)+ Transaction (Session.Session a) deriving (Functor, Applicative, Monad) -- |@@ -56,27 +57,22 @@ deriving (Show, Eq, Ord, Enum, Bounded) -- |--- Execute the transaction using the provided isolation level, mode and a database connection.+-- Execute the transaction using the provided isolation level, mode and database connection. {-# INLINABLE run #-}-run :: Transaction a -> IsolationLevel -> Mode -> Connection.Connection -> IO (Either Query.ResultsError a)-run (Transaction tx) isolation mode connection =- runEitherT $ do- EitherT $ Query.run (Queries.beginTransaction mode') () connection- counterRef <- lift $ newIORef 0- resultEither <- lift $ runEitherT $ runReaderT tx (connection, counterRef)+run :: Transaction a -> IsolationLevel -> Mode -> Session.Session a+run (Transaction session) isolation mode =+ do+ Session.query () (Queries.beginTransaction mode')+ resultEither <- tryError session case resultEither of- Left (Query.ResultError (Query.ServerError code _ _ _))- | code == ErrorCodes.serialization_failure ->- EitherT $ run (Transaction tx) isolation mode connection- _ -> do- result <- EitherT $ pure resultEither- let- query =- if commit- then Queries.commitTransaction- else Queries.abortTransaction- in- EitherT $ Query.run query () connection+ Left error ->+ case error of+ Session.ResultError (Session.ServerError code _ _ _) | code == ErrorCodes.serialization_failure ->+ run (Transaction session) isolation mode+ _ -> + throwError error+ Right result -> do+ Session.query () $ bool Queries.abortTransaction Queries.commitTransaction commit pure result where mode' =@@ -88,9 +84,17 @@ WriteWithoutCommitting -> (True, False) -- |--- Execute a query in the context of a transaction.-{-# INLINABLE query #-}+-- Possibly a multi-statement query,+-- which however cannot be parameterized or prepared,+-- nor can any results of it be collected.+{-# INLINE sql #-}+sql :: ByteString -> Transaction ()+sql sql =+ Transaction $ Session.sql sql++-- |+-- Parameters and a specification of the parametric query to apply them to.+{-# INLINE query #-} query :: a -> Query.Query a b -> Transaction b query params query =- Transaction $ ReaderT $ \(connection, _) -> EitherT $- Query.run query params connection+ Transaction $ Session.query params query
library/Hasql/Transaction/Prelude.hs view
@@ -1,6 +1,7 @@ module Hasql.Transaction.Prelude ( module Exports,+ tryError, ) where @@ -17,6 +18,10 @@ import Control.Monad.Trans.Reader as Exports hiding (liftCallCC, liftCatch) import Control.Monad.Trans.State.Strict as Exports hiding (liftCallCC, liftCatch, liftListen, liftPass) +-- mtl+-------------------------+import Control.Monad.Error.Class as Exports (MonadError (..))+ -- contravariant ------------------------- import Data.Functor.Contravariant as Exports@@ -34,3 +39,7 @@ -- bytestring ------------------------- import Data.ByteString as Exports (ByteString)++tryError :: MonadError e m => m a -> m (Either e a)+tryError m =+ catchError (liftM Right m) (return . Left)
library/Hasql/Transaction/Queries.hs view
@@ -21,7 +21,7 @@ beginTransaction :: TransactionMode -> HQ.Query () () beginTransaction (isolation, write) =- HQ.Query sql HE.unit HD.unit True+ HQ.statement sql HE.unit HD.unit True where sql = TB.toByteString $@@ -43,11 +43,11 @@ commitTransaction :: HQ.Query () () commitTransaction =- HQ.Query "commit" HE.unit HD.unit True+ HQ.statement "commit" HE.unit HD.unit True abortTransaction :: HQ.Query () () abortTransaction =- HQ.Query "abort" HE.unit HD.unit True+ HQ.statement "abort" HE.unit HD.unit True -- * Streaming@@ -55,7 +55,7 @@ declareCursor :: ByteString -> ByteString -> HE.Params a -> HQ.Query a () declareCursor name sql encoder =- HQ.Query sql' encoder HD.unit False+ HQ.statement sql' encoder HD.unit False where sql' = TB.toByteString $@@ -63,11 +63,11 @@ closeCursor :: HQ.Query ByteString () closeCursor =- HQ.Query "CLOSE $1" (HE.value HE.bytea) HD.unit True+ HQ.statement "CLOSE $1" (HE.value HE.bytea) HD.unit True fetchFromCursor :: (b -> a -> b) -> b -> HD.Row a -> HQ.Query (Int64, ByteString) b fetchFromCursor step init rowDec =- HQ.Query sql encoder decoder True+ HQ.statement sql encoder decoder True where sql = "FETCH FORWARD $1 FROM $2"