6 Commits

Author SHA1 Message Date
3e9f22397d chore: prepare v1.3.0 2024-04-11 16:45:35 -05:00
d3be053a8b chore: prepare v1.3.0 2024-04-11 16:45:27 -05:00
1319a4bce7 chore: prepare v1.3.0 2024-04-11 16:45:25 -05:00
8722e69013 feat: generalize PostgresT to MonadPostgres to allow mocking 2024-04-11 16:45:13 -05:00
5dc5912933 chore: prepare v1.2.7 2024-04-11 15:55:22 -05:00
a4d4e6bd75 fix: impl unlift 2024-04-11 15:55:11 -05:00
5 changed files with 149 additions and 91 deletions

View File

@@ -255,59 +255,59 @@ the api of [`node-postgres`]:
- release clients with [`Pool.release`] or [`Pool.destroy`]
- release with [`Pool.end`]
[`Pool`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Pool#t:Pool
[`Config`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Pool#t:Config
[`Pool.make`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Pool#v:make
[`Pool.end`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Pool#v:end
[`Pool.connect`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Pool#v:connect
[`Pool.destroy`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Pool#v:destroy
[`Pool.release`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Pool#v:release
[`Pool`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Pool#t:Pool
[`Config`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Pool#t:Config
[`Pool.make`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Pool#v:make
[`Pool.end`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Pool#v:end
[`Pool.connect`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Pool#v:connect
[`Pool.destroy`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Pool#v:destroy
[`Pool.release`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Pool#v:release
[`Client`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Client#t:Client
[`Client.end`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Client#v:end
[`Client.make`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Client#v:make
[`Client.connected`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Client#v:connected
[`Client.query`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Client#v:query
[`Client.queryRaw`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Client#v:queryRaw
[`Client.exec`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Effect.Aff.Postgres.Client#v:exec
[`Client`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Client#t:Client
[`Client.end`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Client#v:end
[`Client.make`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Client#v:make
[`Client.connected`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Client#v:connected
[`Client.query`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Client#v:query
[`Client.queryRaw`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Client#v:queryRaw
[`Client.exec`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Effect.Aff.Postgres.Client#v:exec
[`Range`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Range#t:Range
[`Range.gt`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Range#v:gt
[`Range.gte`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Range#v:gte
[`Range.lt`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Range#v:lt
[`Range.lte`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Range#v:lte
[`Range`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Range#t:Range
[`Range.gt`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Range#v:gt
[`Range.gte`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Range#v:gte
[`Range.lt`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Range#v:lt
[`Range.lte`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Range#v:lte
[`Raw`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Raw#t:Raw
[`Null`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Raw#t:Null
[`Raw`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Raw#t:Raw
[`Null`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Raw#t:Null
[`Serialize`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres#t:Serialize
[`Deserialize`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres#t:Deserialize
[`Rep`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres#t:Rep
[`modifyPgTypes`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres#v:modifyPgTypes
[`Serialize`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres#t:Serialize
[`Deserialize`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres#t:Deserialize
[`Rep`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres#t:Rep
[`modifyPgTypes`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres#v:modifyPgTypes
[`Result`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Result#t:Result
[`FromRow`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Result#t:FromRow
[`FromRows`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Result#t:FromRows
[`Result`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Result#t:Result
[`FromRow`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Result#t:FromRow
[`FromRows`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Result#t:FromRows
[`Query`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Query#t:Query
[`AsQuery`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Query#t:AsQuery
[`Query`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Query#t:Query
[`AsQuery`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Query#t:AsQuery
[`Query.Builder`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Query.Builder#t:Builder
[`Query.Builder.param`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Query.Builder#v:param
[`Query.Builder.build`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Data.Postgres.Query.Builder#v:build
[`Query.Builder`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Query.Builder#t:Builder
[`Query.Builder.param`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Query.Builder#v:param
[`Query.Builder.build`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Data.Postgres.Query.Builder#v:build
[`MonadCursor`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#t:MonadCursor
[`MonadSession`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#t:MonadSession
[`CursorT`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#t:CursorT
[`SessionT`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#t:SessionT
[`PostgresT`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#t:PostgresT
[`cursor`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#v:cursor
[`session`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#v:session
[`transaction`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#v:transaction
[`runPostgres`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#v:runPostgres
[`query`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#v:query
[`exec`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#v:exec
[`exec_`]: https://pursuit.purescript.org//////////////packages/purescript-postgresql/1.2.6/docs/Control.Monad.Postgres#v:exec_
[`MonadCursor`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#t:MonadCursor
[`MonadSession`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#t:MonadSession
[`CursorT`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#t:CursorT
[`SessionT`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#t:SessionT
[`PostgresT`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#t:PostgresT
[`cursor`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#v:cursor
[`session`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#v:session
[`transaction`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#v:transaction
[`runPostgres`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#v:runPostgres
[`query`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#v:query
[`exec`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#v:exec
[`exec_`]: https://pursuit.purescript.org//////////////////packages/purescript-postgresql/1.3.0/docs/Control.Monad.Postgres#v:exec_
[`node-postgres`]: https://node-postgres.com/
[`pg-types`]: https://github.com/brianc/node-pg-types/

View File

@@ -36,6 +36,7 @@ workspace:
- transformers: ">=6.0.0 <7.0.0"
- tuples: ">=7.0.0 <8.0.0"
- typelevel-prelude: ">=7.0.0 <8.0.0"
- unlift: ">=1.0.1 <2.0.0"
- unsafe-coerce: ">=6.0.0 <7.0.0"
test_dependencies:
- filterable
@@ -74,6 +75,7 @@ workspace:
- fork
- formatters
- free
- freet
- functions
- functors
- gen
@@ -87,6 +89,7 @@ workspace:
- lists
- maybe
- mmorph
- monad-control
- newtype
- node-buffer
- node-child-process
@@ -127,6 +130,7 @@ workspace:
- typelevel-prelude
- unfoldable
- unicode
- unlift
- unsafe-coerce
- variant
package_set:
@@ -924,6 +928,21 @@ packages:
- transformers
- tuples
- unsafe-coerce
freet:
type: registry
version: 7.0.0
integrity: sha256-zkL6wU4ZPq8xz1kGFxoliWqyhBksepMJTyA68VEBaJo=
dependencies:
- aff
- bifunctors
- effect
- either
- exists
- free
- prelude
- tailrec
- transformers
- tuples
functions:
type: registry
version: 6.0.0
@@ -1060,6 +1079,15 @@ packages:
- free
- functors
- transformers
monad-control:
type: registry
version: 5.0.0
integrity: sha256-bgfDW30wbIm70NR1Tvvh9P+VFQMDh1wK2sSJXCj/dZc=
dependencies:
- aff
- freet
- identity
- lists
newtype:
type: registry
version: 5.0.0
@@ -1567,6 +1595,23 @@ packages:
- foldable-traversable
- maybe
- strings
unlift:
type: registry
version: 1.0.1
integrity: sha256-nbBCVV0fZz/3UHKoW11dcTwBYmQOIgK31ht2BN47RPw=
dependencies:
- aff
- effect
- either
- freet
- identity
- lists
- maybe
- monad-control
- prelude
- st
- transformers
- tuples
unsafe-coerce:
type: registry
version: 6.0.0

View File

@@ -1,7 +1,7 @@
package:
name: postgresql
publish:
version: '1.2.6'
version: '1.3.0'
license: 'GPL-3.0-or-later'
location:
githubOwner: 'cakekindel'
@@ -46,6 +46,7 @@ package:
- transformers: ">=6.0.0 <7.0.0"
- tuples: ">=7.0.0 <8.0.0"
- typelevel-prelude: ">=7.0.0 <8.0.0"
- unlift: ">=1.0.1 <2.0.0"
- unsafe-coerce: ">=6.0.0 <7.0.0"
test:
main: Test.Main

View File

@@ -7,18 +7,24 @@ import Control.Alternative (class Plus)
import Control.Monad.Error.Class (class MonadError, class MonadThrow, catchError, throwError)
import Control.Monad.Fork.Class (class MonadBracket, class MonadFork, class MonadKill, bracket, kill, never, uninterruptible)
import Control.Monad.Morph (class MFunctor, class MMonad)
import Control.Monad.Postgres.Cursor (class MonadCursor, CursorT)
import Control.Monad.Postgres.Session (class MonadSession, SessionT, exec, exec_, query)
import Control.Monad.Reader (class MonadAsk, class MonadReader, ReaderT, ask, local, runReaderT)
import Control.Monad.Rec.Class (class MonadRec)
import Control.Monad.Trans.Class (class MonadTrans, lift)
import Control.Parallel (class Parallel, parallel, sequential)
import Data.Newtype (class Newtype, unwrap, wrap)
import Effect.Aff (Fiber)
import Data.Postgres (RepT)
import Data.Postgres.Query (class AsQuery, asQuery)
import Data.Postgres.Raw (Raw)
import Data.Postgres.Result (class FromRow, fromRow)
import Data.Tuple.Nested ((/\))
import Effect.Aff.Class (class MonadAff, liftAff)
import Effect.Aff.Postgres.Pool (Pool)
import Effect.Aff.Postgres.Pool as Pool
import Effect.Aff.Unlift (class MonadUnliftAff)
import Effect.Class (class MonadEffect, liftEffect)
import Effect.Exception (Error)
import Effect.Unlift (class MonadUnliftEffect)
import Prim.Row (class Union)
-- | Monad handling pool resource acquisition & release
@@ -58,6 +64,8 @@ derive newtype instance (Bind m) => Bind (PostgresT m)
derive newtype instance (Monad m) => Monad (PostgresT m)
derive newtype instance (MonadEffect m) => MonadEffect (PostgresT m)
derive newtype instance (MonadAff m) => MonadAff (PostgresT m)
derive newtype instance (MonadUnliftEffect m) => MonadUnliftEffect (PostgresT m)
derive newtype instance (MonadUnliftAff m) => MonadUnliftAff (PostgresT m)
derive newtype instance MonadRec m => MonadRec (PostgresT m)
derive newtype instance MonadTrans (PostgresT)
derive newtype instance (MonadThrow e m) => MonadThrow e (PostgresT m)
@@ -88,29 +96,48 @@ instance (MonadBracket e f m, MonadAff m) => MonadSession (PostgresT m) where
exec = session <<< exec
exec_ = session <<< exec_
-- | Lifts a session to `PostgresT`, releasing the client to the pool
-- | after execution.
session :: forall e f m a. MonadBracket e f m => MonadAff m => MonadSession (SessionT m) => SessionT m a -> PostgresT m a
session m = do
pool <- ask
let
acq = liftAff $ Pool.connect pool
rel _ c = liftEffect $ Pool.release pool c
lift $ bracket acq rel (runReaderT m)
-- | Lifts a session to `PostgresT`, running the session
-- | in a transaction.
-- | Typeclass generalizing `PostgresT`. Allows for dependency-injecting different
-- | implementations of the idea of a postgres connection.
-- |
-- | If the session throws an error, the transaction will be
-- | rolled back and the error rethrown.
transaction :: forall m a. MonadBracket Error Fiber m => MonadAff m => MonadSession (SessionT m) => SessionT m a -> PostgresT m a
transaction m =
let
begin = void $ exec "begin;"
commit = m <* exec "commit;"
rollback e = exec "rollback;" *> throwError e
in
session $ begin *> catchError commit rollback
-- | - `session` - Session monad (for `PostgresT` this is `SessionT`)
-- | - `cursor` - Cursor session monad (for `PostgresT` this is `CursorT`)
-- | - `ct` - Open type parameter for cursor type. Don't pin this to a concrete type.
class (MonadSession session, MonadCursor cursor ct) <= MonadPostgres m session cursor ct | m -> ct cursor session where
-- | Run a session in `m`.
session :: session ~> m
-- | Run a session in `m`, wrapped in a transaction.
-- |
-- | If any errors are raised, the transaction is rolled back and
-- | the error rethrown.
transaction :: session ~> m
-- | `cursor`, but using a custom deserialize function for the data
-- | yielded by the cursor
cursorWith :: forall q. AsQuery q => (Array Raw -> RepT ct) -> String -> q -> cursor ~> m
instance (MonadBracket e f m, MonadAff m, MonadSession (SessionT m), MonadCursor (CursorT t (SessionT m)) t) => MonadPostgres (PostgresT m) (SessionT m) (CursorT ct (SessionT m)) ct where
session m = do
pool <- ask
let
acq = liftAff $ Pool.connect pool
rel _ c = liftEffect $ Pool.release pool c
lift $ bracket acq rel (runReaderT m)
transaction m =
let
begin = void $ exec "begin;"
commit = m <* exec "commit;"
rollback e = exec "rollback;" *> throwError e
in
session $ begin *> catchError commit rollback
cursorWith f cur q m =
transaction do
q' <- liftEffect $ asQuery q
exec_ $ "declare " <> cur <> " cursor for (" <> (unwrap q').text <> ");"
runReaderT (unwrap m) (cur /\ f)
-- | Create a server-side cursor for a query in a transaction,
-- | and execute a `CursorT` with a view to the new cursor.
cursor :: forall @cursort t session cursor q a. MonadPostgres t session cursor cursort => AsQuery q => FromRow cursort => String -> q -> cursor a -> t a
cursor = cursorWith fromRow
-- | Execute a `PostgresT` using an existing connection pool.
-- |

View File

@@ -6,9 +6,8 @@ import Control.Alt (class Alt)
import Control.Alternative (class Plus)
import Control.Monad.Error.Class (class MonadError, class MonadThrow)
import Control.Monad.Fork.Class (class MonadBracket, class MonadFork, class MonadKill, bracket, kill, never, uninterruptible)
import Control.Monad.Postgres.Base (PostgresT, transaction)
import Control.Monad.Postgres.Session (class MonadSession, SessionT, exec, exec_, query)
import Control.Monad.Reader (class MonadAsk, class MonadReader, ReaderT, ask, local, runReaderT)
import Control.Monad.Postgres.Session (class MonadSession, exec, exec_, query)
import Control.Monad.Reader (class MonadAsk, class MonadReader, ReaderT, ask, local)
import Control.Monad.Rec.Class (class MonadRec)
import Control.Monad.Trans.Class (class MonadTrans, lift)
import Control.Parallel (class Parallel, parallel, sequential)
@@ -16,15 +15,13 @@ import Data.Array as Array
import Data.Maybe (Maybe)
import Data.Newtype (class Newtype, unwrap, wrap)
import Data.Postgres (RepT, smash)
import Data.Postgres.Query (class AsQuery, asQuery)
import Data.Postgres.Raw (Raw)
import Data.Postgres.Result (class FromRow, fromRow)
import Data.Traversable (traverse)
import Data.Tuple.Nested (type (/\), (/\))
import Effect.Aff (Fiber)
import Effect.Aff.Class (class MonadAff)
import Effect.Aff.Unlift (class MonadUnliftAff)
import Effect.Class (class MonadEffect, liftEffect)
import Effect.Exception (Error)
import Effect.Unlift (class MonadUnliftEffect)
newtype CursorT :: forall k. Type -> (k -> Type) -> k -> Type
newtype CursorT t m a = CursorT (ReaderT (String /\ (Array Raw -> RepT t)) m a)
@@ -40,6 +37,8 @@ derive newtype instance (Monad m) => Monad (CursorT t m)
derive newtype instance (MonadEffect m) => MonadEffect (CursorT t m)
derive newtype instance (MonadAff m) => MonadAff (CursorT t m)
derive newtype instance MonadRec m => MonadRec (CursorT t m)
derive newtype instance (MonadUnliftEffect m) => MonadUnliftEffect (CursorT t m)
derive newtype instance (MonadUnliftAff m) => MonadUnliftAff (CursorT t m)
derive newtype instance MonadTrans (CursorT t)
derive newtype instance (MonadThrow e m) => MonadThrow e (CursorT t m)
derive newtype instance (MonadError e m) => MonadError e (CursorT t m)
@@ -108,17 +107,3 @@ instance (MonadSession m) => MonadSession (CursorT t m) where
-- | Fetch the next row from the cursor
fetchOne :: forall m t. MonadCursor m t => m (Maybe t)
fetchOne = Array.head <$> fetch 1
-- | Create a server-side cursor for a query in a transaction,
-- | and execute a `CursorT` with a view to the new cursor.
cursor :: forall m @t a q. FromRow t => AsQuery q => MonadAff m => MonadBracket Error Fiber m => MonadSession (SessionT m) => String -> q -> CursorT t (SessionT m) a -> PostgresT m a
cursor cur q m = cursorWith cur q fromRow m
-- | `cursor`, but using a custom deserialize function for the data
-- | yielded by the cursor
cursorWith :: forall m @t a q. AsQuery q => MonadAff m => MonadBracket Error Fiber m => MonadSession (SessionT m) => String -> q -> (Array Raw -> RepT t) -> CursorT t (SessionT m) a -> PostgresT m a
cursorWith cur q f m =
transaction do
q' <- liftEffect $ asQuery q
exec_ $ "declare " <> cur <> " cursor for (" <> (unwrap q').text <> ");"
runReaderT (unwrap m) (cur /\ f)