generated from tpl/purs
Drop ExceptT
from functions
This commit is contained in:
parent
71bbf44227
commit
87d6f7fc95
@ -44,14 +44,15 @@ We assume here that postgres is running on a standard local port
|
|||||||
with `ident` authentication so configuration can be nearly empty (`defaultPoolConfiguration`).
|
with `ident` authentication so configuration can be nearly empty (`defaultPoolConfiguration`).
|
||||||
It requires only database name which we pass to `newPool` function.
|
It requires only database name which we pass to `newPool` function.
|
||||||
We setup also `idleTimeoutMillis` value because this code
|
We setup also `idleTimeoutMillis` value because this code
|
||||||
is run by our test suite and we want to exit after execution quickly ;-)
|
is run by our test suite and we want to exit after its execution quickly ;-)
|
||||||
|
|
||||||
|
|
||||||
```purescript
|
```purescript
|
||||||
run ∷ PG Unit
|
run ∷ PG Unit
|
||||||
run = do
|
run = do
|
||||||
|
|
||||||
pool <- liftEffect $ newPool ((defaultPoolConfiguration "purspg") { idleTimeoutMillis = Just 1000 })
|
pool <- liftEffect $ newPool
|
||||||
|
((defaultPoolConfiguration "purspg") { idleTimeoutMillis = Just 1000 })
|
||||||
withConnection pool \conn -> do
|
withConnection pool \conn -> do
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
module Database.PostgreSQL
|
module Database.PostgreSQL where
|
||||||
( module Row
|
-- ( module Row
|
||||||
, module Value
|
-- , module Value
|
||||||
, PG
|
-- , PG
|
||||||
, PGError(..)
|
-- , PGError(..)
|
||||||
, PGErrorDetail
|
-- , PGErrorDetail
|
||||||
, Database
|
-- , Database
|
||||||
, PoolConfiguration
|
-- , PoolConfiguration
|
||||||
, Pool
|
-- , Pool
|
||||||
, Connection
|
-- , Connection
|
||||||
, Query(..)
|
-- , Query(..)
|
||||||
, newPool
|
-- , newPool
|
||||||
, withConnection
|
-- , withConnection
|
||||||
, withTransaction
|
-- , withTransaction
|
||||||
, defaultPoolConfiguration
|
-- , defaultPoolConfiguration
|
||||||
, command
|
-- , command
|
||||||
, execute
|
-- , execute
|
||||||
, query
|
-- , query
|
||||||
, scalar
|
-- , scalar
|
||||||
, onIntegrityError
|
-- , onIntegrityError
|
||||||
) where
|
-- ) where
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
@ -26,7 +26,8 @@ import Control.Monad.Error.Class (catchError, throwError, try)
|
|||||||
import Control.Monad.Except.Trans (ExceptT, except, runExceptT)
|
import Control.Monad.Except.Trans (ExceptT, except, runExceptT)
|
||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
import Data.Array (head)
|
import Data.Array (head)
|
||||||
import Data.Either (Either(..))
|
import Data.Bifunctor (lmap)
|
||||||
|
import Data.Either (Either(..), either, hush)
|
||||||
import Data.Generic.Rep (class Generic)
|
import Data.Generic.Rep (class Generic)
|
||||||
import Data.Generic.Rep.Show (genericShow)
|
import Data.Generic.Rep.Show (genericShow)
|
||||||
import Data.Maybe (Maybe(..), maybe)
|
import Data.Maybe (Maybe(..), maybe)
|
||||||
@ -34,7 +35,7 @@ import Data.Newtype (class Newtype)
|
|||||||
import Data.Nullable (Nullable, toMaybe, toNullable)
|
import Data.Nullable (Nullable, toMaybe, toNullable)
|
||||||
import Data.String (Pattern(..))
|
import Data.String (Pattern(..))
|
||||||
import Data.String as String
|
import Data.String as String
|
||||||
import Data.Traversable (traverse)
|
import Data.Traversable (sequence, traverse)
|
||||||
import Database.PostgreSQL.Row (class FromSQLRow, class ToSQLRow, Row0(..), Row1(..), Row10(..), Row11(..), Row12(..), Row13(..), Row14(..), Row15(..), Row16(..), Row17(..), Row18(..), Row19(..), Row2(..), Row3(..), Row4(..), Row5(..), Row6(..), Row7(..), Row8(..), Row9(..), fromSQLRow, toSQLRow) as Row
|
import Database.PostgreSQL.Row (class FromSQLRow, class ToSQLRow, Row0(..), Row1(..), Row10(..), Row11(..), Row12(..), Row13(..), Row14(..), Row15(..), Row16(..), Row17(..), Row18(..), Row19(..), Row2(..), Row3(..), Row4(..), Row5(..), Row6(..), Row7(..), Row8(..), Row9(..), fromSQLRow, toSQLRow) as Row
|
||||||
import Database.PostgreSQL.Row (class FromSQLRow, class ToSQLRow, Row0(..), Row1(..), fromSQLRow, toSQLRow)
|
import Database.PostgreSQL.Row (class FromSQLRow, class ToSQLRow, Row0(..), Row1(..), fromSQLRow, toSQLRow)
|
||||||
import Database.PostgreSQL.Value (class FromSQLValue)
|
import Database.PostgreSQL.Value (class FromSQLValue)
|
||||||
@ -48,15 +49,6 @@ import Foreign (Foreign)
|
|||||||
|
|
||||||
type Database = String
|
type Database = String
|
||||||
|
|
||||||
-- | PostgreSQL computations run in the `PG` monad. It's just `Aff` stacked with
|
|
||||||
-- | `ExceptT` to provide error handling.
|
|
||||||
-- |
|
|
||||||
-- | Errors originating from database queries or connection to the database are
|
|
||||||
-- | modeled with the `PGError` type. Use `runExceptT` from
|
|
||||||
-- | `Control.Monad.Except.Trans` to turn a `PG a` action into `Aff (Either
|
|
||||||
-- | PGError a)`.
|
|
||||||
type PG a = ExceptT PGError Aff a
|
|
||||||
|
|
||||||
-- | PostgreSQL connection pool configuration.
|
-- | PostgreSQL connection pool configuration.
|
||||||
type PoolConfiguration =
|
type PoolConfiguration =
|
||||||
{ database :: Database
|
{ database :: Database
|
||||||
@ -123,18 +115,18 @@ foreign import ffiNewPool
|
|||||||
-- | Run an action with a connection. The connection is released to the pool
|
-- | Run an action with a connection. The connection is released to the pool
|
||||||
-- | when the action returns.
|
-- | when the action returns.
|
||||||
withConnection
|
withConnection
|
||||||
:: ∀ a
|
:: forall a
|
||||||
. Pool
|
. Pool
|
||||||
-> (Connection -> PG a)
|
-> (Either PGError Connection -> Aff a)
|
||||||
-> PG a
|
-> Aff a
|
||||||
withConnection p k =
|
withConnection p k =
|
||||||
except <=< lift $ bracket (connect p) cleanup run
|
bracket (connect p) cleanup run
|
||||||
where
|
where
|
||||||
cleanup (Left _) = pure unit
|
cleanup (Left _) = pure unit
|
||||||
cleanup (Right { done }) = liftEffect done
|
cleanup (Right { done }) = liftEffect done
|
||||||
|
|
||||||
run (Left err) = pure $ Left err
|
run (Left err) = k (Left err)
|
||||||
run (Right { connection }) = runExceptT $ k connection
|
run (Right { connection }) = k (Right connection)
|
||||||
|
|
||||||
connect
|
connect
|
||||||
:: Pool
|
:: Pool
|
||||||
@ -152,92 +144,89 @@ type ConnectResult =
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreign import ffiConnect
|
foreign import ffiConnect
|
||||||
:: ∀ a
|
:: forall a
|
||||||
. { nullableLeft :: Error -> Nullable (Either PGError ConnectResult)
|
. { nullableLeft :: Error -> Nullable (Either PGError ConnectResult)
|
||||||
, right :: a -> Either PGError ConnectResult
|
, right :: a -> Either PGError ConnectResult
|
||||||
}
|
}
|
||||||
-> Pool
|
-> Pool
|
||||||
-> EffectFnAff (Either PGError ConnectResult)
|
-> EffectFnAff (Either PGError ConnectResult)
|
||||||
|
|
||||||
-- | Run an action within a transaction. The transaction is committed if the
|
-- -- | Run an action within a transaction. The transaction is committed if the
|
||||||
-- | action returns cleanly, and rolled back if the action throws (either a
|
-- -- | action returns cleanly, and rolled back if the action throws (either a
|
||||||
-- | `PGError` or a JavaScript exception in the Aff context). If you want to
|
-- -- | `PGError` or a JavaScript exception in the Aff context). If you want to
|
||||||
-- | change the transaction mode, issue a separate `SET TRANSACTION` statement
|
-- -- | change the transaction mode, issue a separate `SET TRANSACTION` statement
|
||||||
-- | within the transaction.
|
-- -- | within the transaction.
|
||||||
withTransaction
|
-- withTransaction
|
||||||
:: ∀ a
|
-- :: forall a
|
||||||
. Connection
|
-- . Connection
|
||||||
-> PG a
|
-- -> (Maybe PGError -> Aff a)
|
||||||
-> PG a
|
-- -> Aff a
|
||||||
withTransaction conn action =
|
-- withTransaction conn action =
|
||||||
begin *> lift (try $ runExceptT action) >>= case _ of
|
-- begin *> lift (try $ runExceptT action) >>= case _ of
|
||||||
Left jsErr -> do
|
-- Left jsErr -> do
|
||||||
rollback
|
-- rollback
|
||||||
lift $ throwError jsErr
|
-- lift $ throwError jsErr
|
||||||
Right (Left pgErr) -> do
|
-- Right (Left pgErr) -> do
|
||||||
rollback
|
-- rollback
|
||||||
throwError pgErr
|
-- throwError pgErr
|
||||||
Right (Right value) -> do
|
-- Right (Right value) -> do
|
||||||
commit
|
-- commit
|
||||||
pure value
|
-- pure value
|
||||||
|
--
|
||||||
where
|
-- where
|
||||||
begin = execute conn (Query "BEGIN TRANSACTION") Row0
|
-- begin = execute conn (Query "BEGIN TRANSACTION") Row0
|
||||||
commit = execute conn (Query "COMMIT TRANSACTION") Row0
|
-- commit = execute conn (Query "COMMIT TRANSACTION") Row0
|
||||||
rollback = execute conn (Query "ROLLBACK TRANSACTION") Row0
|
-- rollback = execute conn (Query "ROLLBACK TRANSACTION") Row0
|
||||||
|
|
||||||
-- | Execute a PostgreSQL query and discard its results.
|
-- | Execute a PostgreSQL query and discard its results.
|
||||||
execute
|
execute
|
||||||
:: ∀ i o
|
:: forall i o
|
||||||
. (ToSQLRow i)
|
. (ToSQLRow i)
|
||||||
=> Connection
|
=> Connection
|
||||||
-> Query i o
|
-> Query i o
|
||||||
-> i
|
-> i
|
||||||
-> PG Unit
|
-> Aff (Maybe PGError)
|
||||||
execute conn (Query sql) values =
|
execute conn (Query sql) values =
|
||||||
void $ unsafeQuery conn sql (toSQLRow values)
|
hush <<< either Right Left <$> unsafeQuery conn sql (toSQLRow values)
|
||||||
|
|
||||||
-- | Execute a PostgreSQL query and return its results.
|
-- | Execute a PostgreSQL query and return its results.
|
||||||
query
|
query
|
||||||
:: ∀ i o
|
:: forall i o
|
||||||
. ToSQLRow i
|
. ToSQLRow i
|
||||||
=> FromSQLRow o
|
=> FromSQLRow o
|
||||||
=> Connection
|
=> Connection
|
||||||
-> Query i o
|
-> Query i o
|
||||||
-> i
|
-> i
|
||||||
-> PG (Array o)
|
-> Aff (Either PGError (Array o))
|
||||||
query conn (Query sql) values = do
|
query conn (Query sql) values = do
|
||||||
_.rows <$> unsafeQuery conn sql (toSQLRow values)
|
r <- unsafeQuery conn sql (toSQLRow values)
|
||||||
>>= traverse (fromSQLRow >>> case _ of
|
pure $ r >>= _.rows >>> traverse (fromSQLRow >>> lmap ConversionError)
|
||||||
Right row -> pure row
|
|
||||||
Left msg -> throwError $ ConversionError msg)
|
|
||||||
|
|
||||||
-- | Execute a PostgreSQL query and return the first field of the first row in
|
-- | Execute a PostgreSQL query and return the first field of the first row in
|
||||||
-- | the result.
|
-- | the result.
|
||||||
scalar
|
scalar
|
||||||
:: ∀ i o
|
:: forall i o
|
||||||
. ToSQLRow i
|
. ToSQLRow i
|
||||||
=> FromSQLValue o
|
=> FromSQLValue o
|
||||||
=> Connection
|
=> Connection
|
||||||
-> Query i (Row1 o)
|
-> Query i (Row1 o)
|
||||||
-> i
|
-> i
|
||||||
-> PG (Maybe o)
|
-> Aff (Either PGError (Maybe o))
|
||||||
scalar conn sql values =
|
scalar conn sql values =
|
||||||
query conn sql values
|
query conn sql values <#> map (head >>> map (case _ of Row1 a -> a))
|
||||||
<#> map (case _ of Row1 a -> a) <<< head
|
|
||||||
|
|
||||||
-- | Execute a PostgreSQL query and return its command tag value
|
-- | Execute a PostgreSQL query and return its command tag value
|
||||||
-- | (how many rows were affected by the query). This may be useful
|
-- | (how many rows were affected by the query). This may be useful
|
||||||
-- | for example with `DELETE` or `UPDATE` queries.
|
-- | for example with `DELETE` or `UPDATE` queries.
|
||||||
command
|
command
|
||||||
:: ∀ i
|
:: forall i
|
||||||
. ToSQLRow i
|
. ToSQLRow i
|
||||||
=> Connection
|
=> Connection
|
||||||
-> Query i Int
|
-> Query i Int
|
||||||
-> i
|
-> i
|
||||||
-> PG Int
|
-> Aff (Either PGError Int)
|
||||||
command conn (Query sql) values =
|
command conn (Query sql) values =
|
||||||
_.rowCount <$> unsafeQuery conn sql (toSQLRow values)
|
map _.rowCount <$> unsafeQuery conn sql (toSQLRow values)
|
||||||
|
|
||||||
type QueryResult =
|
type QueryResult =
|
||||||
{ rows :: Array (Array Foreign)
|
{ rows :: Array (Array Foreign)
|
||||||
@ -248,9 +237,9 @@ unsafeQuery
|
|||||||
:: Connection
|
:: Connection
|
||||||
-> String
|
-> String
|
||||||
-> Array Foreign
|
-> Array Foreign
|
||||||
-> PG QueryResult
|
-> Aff (Either PGError QueryResult)
|
||||||
unsafeQuery c s =
|
unsafeQuery c s =
|
||||||
except <=< lift <<< fromEffectFnAff <<< ffiUnsafeQuery p c s
|
fromEffectFnAff <<< ffiUnsafeQuery p c s
|
||||||
where
|
where
|
||||||
p =
|
p =
|
||||||
{ nullableLeft: toNullable <<< map Left <<< convertError
|
{ nullableLeft: toNullable <<< map Left <<< convertError
|
||||||
@ -340,11 +329,11 @@ convertError err =
|
|||||||
prefix p =
|
prefix p =
|
||||||
maybe false (_ == 0) <<< String.indexOf (Pattern p)
|
maybe false (_ == 0) <<< String.indexOf (Pattern p)
|
||||||
|
|
||||||
onIntegrityError :: forall a. PG a -> PG a -> PG a
|
-- onIntegrityError :: forall a. PG a -> PG a -> PG a
|
||||||
onIntegrityError errorResult db =
|
-- onIntegrityError errorResult db =
|
||||||
catchError db handleError
|
-- catchError db handleError
|
||||||
where
|
-- where
|
||||||
handleError e =
|
-- handleError e =
|
||||||
case e of
|
-- case e of
|
||||||
IntegrityError _ -> errorResult
|
-- IntegrityError _ -> errorResult
|
||||||
_ -> throwError e
|
-- _ -> throwError e
|
||||||
|
Loading…
Reference in New Issue
Block a user