postgresql-tx-query 0.1.0.0 → 0.2.0.0
raw patch · 6 files changed
+203/−54 lines, 6 filesdep +exceptionsdep +monad-controldep +postgresql-tx-simpledep ~postgresql-txdep ~postgresql-tx-monad-loggernew-uploader
Dependencies added: exceptions, monad-control, postgresql-tx-simple, transformers-base
Dependency ranges changed: postgresql-tx, postgresql-tx-monad-logger
Files
- CHANGELOG.md +10/−1
- package.yaml +8/−4
- postgresql-tx-query.cabal +10/−6
- src/Database/PostgreSQL/Tx/Query.hs +72/−42
- src/Database/PostgreSQL/Tx/Query/Internal.hs +97/−0
- src/Database/PostgreSQL/Tx/Query/Internal/Reexport.hs +6/−1
CHANGELOG.md view
@@ -1,5 +1,14 @@ # Change log +## 0.2.0.0++* Updated for postgresql-tx-0.2.0.0.+* Added `HasCallStack` constraints in transaction runners.+* Added more transaction runners: `pgWithTransactionSerializable`, `pgWithTransactionModeRetry`.+* Added `pgWithSavepoint`.+* Added `pgQueryWithMasker`, `pgExecuteWithMasker`.+* Moved internals to an `Internal` module.+ ## 0.1.0.0 -Initial release+* Initial release
package.yaml view
@@ -1,6 +1,6 @@ name: postgresql-tx-query-version: 0.1.0.0-github: "simspace/postgresql-tx/query"+version: 0.2.0.0+github: "simspace/postgresql-tx" license: BSD3 license-file: LICENSE.md author: "Cary Robbins"@@ -20,13 +20,17 @@ dependencies: - base >= 4.7 && < 5+- exceptions >= 0.10.4 && < 0.11+- monad-control >= 1.0.2.3 && < 1.1 - monad-logger >= 0.3.32 && < 0.4 - mtl >= 2.2.2 && < 2.3 - postgresql-query >= 3.5.0 && < 3.6 - postgresql-simple >= 0.6.2 && < 0.7-- postgresql-tx >= 0.1.0.0 && < 0.2-- postgresql-tx-monad-logger >= 0.1.0.0 && < 0.2+- postgresql-tx >= 0.2.0.0 && < 0.3+- postgresql-tx-monad-logger >= 0.2.0.0 && < 0.3+- postgresql-tx-simple >= 0.2.0.0 && < 0.3 - transformers >= 0.5.6.2 && < 0.6+- transformers-base >= 0.4.5.2 && < 0.5 library: source-dirs: src
postgresql-tx-query.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.33.0.+-- This file has been generated from package.yaml by hpack version 0.31.2. -- -- see: https://github.com/sol/hpack ----- hash: 6e3ca7ec1f2e454d1e99e74cb23491feeec03749caaa5915dd4ab56d4196f856+-- hash: de75a082fc842191537ebebf90b7cab40f5bc05129aa56df357a75d3f0928172 name: postgresql-tx-query-version: 0.1.0.0+version: 0.2.0.0 synopsis: postgresql-tx interfacing for use with postgresql-query. description: Please see the README on GitHub at <https://github.com/simspace/postgresql-tx#readme> category: Database@@ -27,11 +27,11 @@ source-repository head type: git location: https://github.com/simspace/postgresql-tx- subdir: query library exposed-modules: Database.PostgreSQL.Tx.Query+ Database.PostgreSQL.Tx.Query.Internal Database.PostgreSQL.Tx.Query.Internal.Reexport other-modules: Paths_postgresql_tx_query@@ -40,11 +40,15 @@ ghc-options: -Wall build-depends: base >=4.7 && <5+ , exceptions >=0.10.4 && <0.11+ , monad-control >=1.0.2.3 && <1.1 , monad-logger >=0.3.32 && <0.4 , mtl >=2.2.2 && <2.3 , postgresql-query >=3.5.0 && <3.6 , postgresql-simple >=0.6.2 && <0.7- , postgresql-tx >=0.1.0.0 && <0.2- , postgresql-tx-monad-logger >=0.1.0.0 && <0.2+ , postgresql-tx >=0.2.0.0 && <0.3+ , postgresql-tx-monad-logger >=0.2.0.0 && <0.3+ , postgresql-tx-simple >=0.2.0.0 && <0.3 , transformers >=0.5.6.2 && <0.6+ , transformers-base >=0.4.5.2 && <0.5 default-language: Haskell2010
src/Database/PostgreSQL/Tx/Query.hs view
@@ -1,61 +1,91 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE RankNTypes #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Database.PostgreSQL.Tx.Query- ( module Database.PostgreSQL.Tx.Query+ ( PgQueryEnv+ , PgQueryM+ , Logger+ , module Database.PostgreSQL.Tx.Query , module Database.PostgreSQL.Tx.Query.Internal.Reexport ) where -import Control.Monad.Logger (LoggingT, runLoggingT)-import Control.Monad.Trans (MonadTrans(lift))+import Control.Exception (Exception) import Data.Int (Int64)-import Database.PostgreSQL.Tx (Tx(TxEnv, tx), UnsafeTx(unsafeIOTx), TxM, unsafeRunTxM)+import Database.PostgreSQL.Tx (TxM)+import Database.PostgreSQL.Tx.Query.Internal import Database.PostgreSQL.Tx.Query.Internal.Reexport+import GHC.Stack (HasCallStack) import qualified Database.PostgreSQL.Query as Query-import qualified Database.PostgreSQL.Simple as Simple import qualified Database.PostgreSQL.Simple.Transaction as Simple-import qualified Database.PostgreSQL.Tx.MonadLogger--type PgQueryM = PgMonadT (LoggingT TxM)--type Logger = Database.PostgreSQL.Tx.MonadLogger.Logger+import qualified Database.PostgreSQL.Tx.Simple as Tx.Simple -pgWithTransaction :: (Simple.Connection, Logger) -> TxM a -> IO a+-- | Analogue of 'Query.pgWithTransaction'.+--+-- @since 0.1.0.0+pgWithTransaction+ :: (PgQueryEnv r, HasCallStack)+ => r -> (HasCallStack => TxM r a) -> IO a pgWithTransaction = unsafeRunPgQueryTransaction Query.pgWithTransaction -pgWithTransactionMode :: Simple.TransactionMode -> (Simple.Connection, Logger) -> TxM a -> IO a+-- | Analogue of 'Query.pgWithTransactionMode'.+--+-- @since 0.1.0.0+pgWithTransactionMode+ :: (PgQueryEnv r, HasCallStack)+ => Simple.TransactionMode -> r -> (HasCallStack => TxM r a) -> IO a pgWithTransactionMode m = unsafeRunPgQueryTransaction (Query.pgWithTransactionMode m) --- Re-export of 'Query.pgQuery'-pgQuery :: (ToSqlBuilder q, FromRow r) => q -> PgQueryM [r]-pgQuery = unsafeIOTx . Query.pgQuery+-- | Analogue of 'Query.pgWithTransactionSerializable'+-- Unlike @postgresql-query@, uses 'shouldRetryTx' to also retry+-- on @deadlock_detected@, not just @serialization_failure@.+--+-- Note that any 'IO' that occurs inside the 'TxM' may be executed multiple times.+--+-- @since 0.2.0.0+pgWithTransactionSerializable+ :: (PgQueryEnv r, HasCallStack)+ => r -> (HasCallStack => TxM r a) -> IO a+pgWithTransactionSerializable = Tx.Simple.withTransactionSerializable --- Re-export of 'Query.pgExecute'-pgExecute :: (ToSqlBuilder q) => q -> PgQueryM Int64-pgExecute = unsafeIOTx . Query.pgExecute+-- | Analogue of 'Query.pgWithTransactionModeRetry'.+-- You should generally prefer 'pgWithTransactionSerializable'.+--+-- Note that any 'IO' that occurs inside the 'TxM' may be executed multiple times.+--+-- @since 0.2.0.0+pgWithTransactionModeRetry+ :: (PgQueryEnv r, Exception e, HasCallStack)+ => Simple.TransactionMode -> (e -> Bool) -> r -> (HasCallStack => TxM r a) -> IO a+pgWithTransactionModeRetry = Tx.Simple.withTransactionModeRetry -unsafePgQueryIOTx :: PgMonadT (LoggingT IO) a -> PgQueryM a-unsafePgQueryIOTx = unsafeIOTx+-- | Analogue of 'Query.pgWithSavepoint'.+--+-- @since 0.2.0.0+pgWithSavepoint :: (HasCallStack => PgQueryM a) -> PgQueryM a+pgWithSavepoint x =+ unsafeFromPgQueryIO+ $ Query.pgWithSavepoint+ $ unsafeToPgQueryIO x -unsafeRunPgQueryTransaction- :: (PgMonadT (LoggingT IO) a -> PgMonadT (LoggingT IO) a)- -> (Simple.Connection, Logger)- -> TxM a- -> IO a-unsafeRunPgQueryTransaction f (c, logger) x =- unsafeRunTxM- $ tx (c, logger)- $ unsafePgQueryIOTx- $ f- $ lift . lift- $ unsafeRunTxM x+-- | Analogue of 'Query.pgQuery'.+--+-- @since 0.1.0.0+pgQuery :: (ToSqlBuilder q, FromRow r, HasCallStack) => q -> PgQueryM [r]+pgQuery = unsafeFromPgQueryIO . Query.pgQuery -instance Tx PgQueryM where- type TxEnv PgQueryM = (Simple.Connection, Logger)- tx (conn, logger) x = runLoggingT (runPgMonadT conn x) logger+-- | Analogue of 'Query.pgQueryWithMasker'.+--+-- @since 0.2.0.0+pgQueryWithMasker :: (ToSqlBuilder q, FromRow r, HasCallStack) => LogMasker -> q -> PgQueryM [r]+pgQueryWithMasker masker = unsafeFromPgQueryIO . Query.pgQueryWithMasker masker -instance (UnsafeTx io t) => UnsafeTx (PgMonadT io) (PgMonadT t) where- unsafeIOTx (PgMonadT x) = PgMonadT $ unsafeIOTx x+-- | Analogue of 'Query.pgExecute'.+--+-- @since 0.1.0.0+pgExecute :: (ToSqlBuilder q, HasCallStack) => q -> PgQueryM Int64+pgExecute = unsafeFromPgQueryIO . Query.pgExecute++-- | Analogue of 'Query.pgExecuteWithMasker'.+--+-- @since 0.2.0.0+pgExecuteWithMasker :: (ToSqlBuilder q, HasCallStack) => LogMasker -> q -> PgQueryM Int64+pgExecuteWithMasker masker = unsafeFromPgQueryIO . Query.pgExecuteWithMasker masker
+ src/Database/PostgreSQL/Tx/Query/Internal.hs view
@@ -0,0 +1,97 @@+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE GeneralisedNewtypeDeriving #-}+module Database.PostgreSQL.Tx.Query.Internal+ ( -- * Disclaimer+ -- $disclaimer++ -- ** Internals+ module Database.PostgreSQL.Tx.Query.Internal+ ) where++import Control.Monad.Base (MonadBase)+import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)+import Control.Monad.IO.Class (MonadIO)+import Control.Monad.Logger (MonadLogger(monadLoggerLog), MonadLoggerIO(askLoggerIO), toLogStr)+import Control.Monad.Reader (ReaderT(ReaderT))+import Control.Monad.Trans.Control (MonadBaseControl)+import Data.Kind (Constraint)+import Database.PostgreSQL.Tx (TxEnvs, TxM, askTxEnv, mapExceptionTx)+import Database.PostgreSQL.Tx.Query.Internal.Reexport+import Database.PostgreSQL.Tx.Unsafe (unsafeMkTxM, unsafeRunIOInTxM, unsafeRunTxM, unsafeUnTxM)+import GHC.Stack (HasCallStack)+import qualified Database.PostgreSQL.Simple as Simple+import qualified Database.PostgreSQL.Tx.MonadLogger+import qualified Database.PostgreSQL.Tx.Simple.Internal as Tx.Simple.Internal++-- | Runtime environment needed to run @postgresql-query@ via @postgresql-tx@.+--+-- @since 0.2.0.0+type PgQueryEnv r = (TxEnvs '[Simple.Connection, Logger] r) :: Constraint++-- | Monad type alias for running @postgresql-query@ via @postgresql-tx@.+--+-- @since 0.2.0.0+type PgQueryM a = forall r. (PgQueryEnv r) => TxM r a++-- | Re-export of 'Database.PostgreSQL.Tx.MonadLogger.Logger'.+--+-- @since 0.1.0.0+type Logger = Database.PostgreSQL.Tx.MonadLogger.Logger++-- | Analogous to 'TxM' but allows for 'IO'. Useful so we can have+-- instances which are required to run @postgresql-query@ functions.+-- See 'unsafeToPgQueryIO' and 'unsafeFromPgQueryIO' for converting to/from+-- 'TxM'.+newtype UnsafePgQueryIO r a = UnsafePgQueryIO (ReaderT r IO a)+ deriving newtype+ ( Functor, Applicative, Monad, MonadIO+ , MonadBase IO, MonadBaseControl IO, TransactionSafe+ , MonadCatch, MonadMask, MonadThrow+ )++instance (PgQueryEnv r) => HasPostgres (UnsafePgQueryIO r) where+ withPGConnection f = do+ unsafeToPgQueryIO do+ conn <- askTxEnv+ unsafeFromPgQueryIO $ f conn++instance (PgQueryEnv r) => MonadLogger (UnsafePgQueryIO r) where+ monadLoggerLog loc src lvl msg = do+ unsafeToPgQueryIO do+ logger <- askTxEnv+ unsafeRunIOInTxM $ logger loc src lvl (toLogStr msg)++instance (PgQueryEnv r) => MonadLoggerIO (UnsafePgQueryIO r) where+ askLoggerIO = unsafeToPgQueryIO askTxEnv++unsafeToPgQueryIO :: (HasCallStack) => TxM r a -> UnsafePgQueryIO r a+unsafeToPgQueryIO x = UnsafePgQueryIO $ unsafeUnTxM x++unsafeFromPgQueryIO :: (HasCallStack) => UnsafePgQueryIO r a -> TxM r a+unsafeFromPgQueryIO (UnsafePgQueryIO (ReaderT f)) =+ mapExceptionTx (Just . Tx.Simple.Internal.fromSqlError) do+ unsafeMkTxM f++unsafeRunPgQueryTransaction+ :: (PgQueryEnv r, HasCallStack)+ => (HasCallStack => UnsafePgQueryIO r a -> UnsafePgQueryIO r a)+ -> r+ -> TxM r a+ -> IO a+unsafeRunPgQueryTransaction f r x =+ unsafeRunTxM r+ $ unsafeFromPgQueryIO+ $ f+ $ unsafeToPgQueryIO x++-- $disclaimer+--+-- Changes to this module will not be reflected in the library's version+-- updates.
src/Database/PostgreSQL/Tx/Query/Internal/Reexport.hs view
@@ -10,8 +10,13 @@ ) -- Don't re-export names that we define in 'Database.PostgreSQL.Tx.Query'. import Database.PostgreSQL.Query as X hiding- ( pgWithTransaction+ ( pgWithSavepoint+ , pgWithTransaction , pgWithTransactionMode+ , pgWithTransactionModeRetry+ , pgWithTransactionSerializable , pgQuery+ , pgQueryWithMasker , pgExecute+ , pgExecuteWithMasker )