diff --git a/README.md b/README.md index ebfb3ae..e45e701 100644 --- a/README.md +++ b/README.md @@ -18,11 +18,14 @@ module Test.README where import Prelude -import Database.PostgreSQL.PG (defaultPoolConfiguration, command, execute, newPool, query, Query(Query), withConnection, withTransaction) +import Control.Monad.Except.Trans (ExceptT, runExceptT) +import Database.PostgreSQL.PG (defaultPoolConfiguration, PGError, command, execute, newPool, Pool, Connection, query, Query(Query)) +import Database.PostgreSQL.PG as PG import Database.PostgreSQL.Row (Row0(Row0), Row3(Row3)) import Data.Decimal as Decimal import Data.Maybe (Maybe(..)) import Data.Tuple.Nested ((/\)) +import Effect.Aff (Aff) import Effect.Class (liftEffect) import Test.Assert (assert) ``` @@ -30,14 +33,21 @@ import Test.Assert (assert) The whole API for interaction with PostgreSQL is performed asynchronously in `Aff` (the only function which runs in plain `Effect` is `newPool`). Core library functions usually results in somthing like `Aff (Either PGError a)` which can be easily -wrapped by user into `ExceptT` or any other custom monad stack. To be honest we provides predifined `ExceptT` -versions of functions in `Database.PostgreSQL.PG` along with some `hoist*` helpers. +wrapped by user into `ExceptT` or any other custom monad stack. +To be honest we provide alternatives to functions in the `Database.PostgreSQL.PG` module that work on any stack `m` with `MonadError PGError m` and `MonadAff m`. +The module contains two functions `withConnection` and `withTransaction` that require additional parameter - a transformation from a custom monad stack to `Aff (Either PGError a)`. We are going to work with `PG` type in this tutorial but please don't consider it as the only option if you encounter any troubles integrating it into your own app monad stack. - ```purescript - type PG a = ExceptT PGError Aff a - ``` +```purescript +type PG a = ExceptT PGError Aff a + +withConnection :: forall a. Pool -> (Connection -> PG a) -> PG a +withConnection = PG.withConnection runExceptT + +withTransaction :: forall a. Connection -> PG a -> PG a +withTransaction = PG.withTransaction runExceptT +``` We assume here that Postgres is running on a standard local port with `ident` authentication so configuration can be nearly empty (`defaultPoolConfiguration`). diff --git a/src/Database/PostgreSQL/PG.purs b/src/Database/PostgreSQL/PG.purs index 06a9cd0..d7908d7 100644 --- a/src/Database/PostgreSQL/PG.purs +++ b/src/Database/PostgreSQL/PG.purs @@ -37,11 +37,11 @@ withConnection :: forall a m . MonadError PGError m => MonadAff m - => Pool - -> (m a -> Aff (Either PGError a)) + => (m a -> Aff (Either PGError a)) + -> Pool -> (Connection -> m a) -> m a -withConnection p f k = do +withConnection f p k = do res <- liftAff $ P.withConnection p case _ of Right conn -> f $ k conn Left pgErr -> pure $ Left pgErr @@ -56,11 +56,11 @@ withTransaction :: forall a m . MonadAff m => MonadError PGError m - => Connection - -> (m a -> Aff (Either PGError a)) + => (m a -> Aff (Either PGError a)) + -> Connection -> m a -> m a -withTransaction conn f action = do +withTransaction f conn action = do res <- liftAff $ P.withTransaction conn (f action) either throwError pure $ join res diff --git a/test/Main.purs b/test/Main.purs index 1ecb4c1..3c46c58 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -5,7 +5,7 @@ module Test.Main import Prelude import Control.Monad.Error.Class (throwError, try) -import Control.Monad.Except.Trans (ExceptT, runExceptT) +import Control.Monad.Except.Trans (runExceptT) import Control.Monad.Trans.Class (lift) import Data.Array (zip) import Data.Date (Date, canonicalDate) @@ -21,7 +21,6 @@ import Data.Newtype (unwrap) import Data.Tuple (Tuple(..)) import Data.Tuple.Nested ((/\)) import Database.PostgreSQL.PG (Connection, PGError(..), Pool, PoolConfiguration, Query(Query), Row0(Row0), Row1(Row1), Row2(Row2), Row3(Row3), Row9(Row9), command, execute, newPool, onIntegrityError, query, scalar) -import Database.PostgreSQL.PG as PG import Effect (Effect) import Effect.Aff (Aff, error, launchAff) import Effect.Class (liftEffect) @@ -31,18 +30,19 @@ import Global.Unsafe (unsafeStringify) import Math ((%)) import Partial.Unsafe (unsafePartial) import Test.Assert (assert) +import Test.README (run, PG, withConnection, withTransaction) as README import Test.Unit (TestSuite, suite) import Test.Unit as Test.Unit import Test.Unit.Assert (equal) import Test.Unit.Main (runTest) -type PG a = ExceptT PGError Aff a +type PG a = README.PG a withConnection :: forall a. Pool -> (Connection -> PG a) -> PG a -withConnection conn = PG.withConnection conn runExceptT +withConnection = README.withConnection withTransaction :: forall a. Connection -> PG a -> PG a -withTransaction conn = PG.withTransaction conn runExceptT +withTransaction = README.withTransaction pgEqual :: forall a. Eq a => Show a => a -> a -> PG Unit pgEqual a b = lift $ equal a b