module Hasql.CursorTransaction.Private.CursorTransaction where

import qualified ByteString.TreeBuilder as E
import Hasql.CursorTransaction.Private.Prelude
import qualified Hasql.CursorTransaction.Private.Specs as G
import qualified Hasql.CursorTransaction.Private.Transactions as C
import qualified Hasql.Decoders as F
import qualified Hasql.Encoders as D
import qualified Hasql.Transaction as A

-- |
-- Context for fetching from multiple cursors in an intertwined fashion.
newtype CursorTransaction s result
  = CursorTransaction (StateT (Int, A.Transaction ()) A.Transaction result)
  deriving ((forall a b.
 (a -> b) -> CursorTransaction s a -> CursorTransaction s b)
-> (forall a b.
    a -> CursorTransaction s b -> CursorTransaction s a)
-> Functor (CursorTransaction s)
forall a b. a -> CursorTransaction s b -> CursorTransaction s a
forall a b.
(a -> b) -> CursorTransaction s a -> CursorTransaction s b
forall s a b. a -> CursorTransaction s b -> CursorTransaction s a
forall s a b.
(a -> b) -> CursorTransaction s a -> CursorTransaction s b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall s a b.
(a -> b) -> CursorTransaction s a -> CursorTransaction s b
fmap :: forall a b.
(a -> b) -> CursorTransaction s a -> CursorTransaction s b
$c<$ :: forall s a b. a -> CursorTransaction s b -> CursorTransaction s a
<$ :: forall a b. a -> CursorTransaction s b -> CursorTransaction s a
Functor, Functor (CursorTransaction s)
Functor (CursorTransaction s) =>
(forall a. a -> CursorTransaction s a)
-> (forall a b.
    CursorTransaction s (a -> b)
    -> CursorTransaction s a -> CursorTransaction s b)
-> (forall a b c.
    (a -> b -> c)
    -> CursorTransaction s a
    -> CursorTransaction s b
    -> CursorTransaction s c)
-> (forall a b.
    CursorTransaction s a
    -> CursorTransaction s b -> CursorTransaction s b)
-> (forall a b.
    CursorTransaction s a
    -> CursorTransaction s b -> CursorTransaction s a)
-> Applicative (CursorTransaction s)
forall s. Functor (CursorTransaction s)
forall a. a -> CursorTransaction s a
forall s a. a -> CursorTransaction s a
forall a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s a
forall a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s b
forall a b.
CursorTransaction s (a -> b)
-> CursorTransaction s a -> CursorTransaction s b
forall s a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s a
forall s a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s b
forall s a b.
CursorTransaction s (a -> b)
-> CursorTransaction s a -> CursorTransaction s b
forall a b c.
(a -> b -> c)
-> CursorTransaction s a
-> CursorTransaction s b
-> CursorTransaction s c
forall s a b c.
(a -> b -> c)
-> CursorTransaction s a
-> CursorTransaction s b
-> CursorTransaction s c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall s a. a -> CursorTransaction s a
pure :: forall a. a -> CursorTransaction s a
$c<*> :: forall s a b.
CursorTransaction s (a -> b)
-> CursorTransaction s a -> CursorTransaction s b
<*> :: forall a b.
CursorTransaction s (a -> b)
-> CursorTransaction s a -> CursorTransaction s b
$cliftA2 :: forall s a b c.
(a -> b -> c)
-> CursorTransaction s a
-> CursorTransaction s b
-> CursorTransaction s c
liftA2 :: forall a b c.
(a -> b -> c)
-> CursorTransaction s a
-> CursorTransaction s b
-> CursorTransaction s c
$c*> :: forall s a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s b
*> :: forall a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s b
$c<* :: forall s a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s a
<* :: forall a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s a
Applicative, Applicative (CursorTransaction s)
Applicative (CursorTransaction s) =>
(forall a b.
 CursorTransaction s a
 -> (a -> CursorTransaction s b) -> CursorTransaction s b)
-> (forall a b.
    CursorTransaction s a
    -> CursorTransaction s b -> CursorTransaction s b)
-> (forall a. a -> CursorTransaction s a)
-> Monad (CursorTransaction s)
forall s. Applicative (CursorTransaction s)
forall a. a -> CursorTransaction s a
forall s a. a -> CursorTransaction s a
forall a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s b
forall a b.
CursorTransaction s a
-> (a -> CursorTransaction s b) -> CursorTransaction s b
forall s a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s b
forall s a b.
CursorTransaction s a
-> (a -> CursorTransaction s b) -> CursorTransaction s b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall s a b.
CursorTransaction s a
-> (a -> CursorTransaction s b) -> CursorTransaction s b
>>= :: forall a b.
CursorTransaction s a
-> (a -> CursorTransaction s b) -> CursorTransaction s b
$c>> :: forall s a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s b
>> :: forall a b.
CursorTransaction s a
-> CursorTransaction s b -> CursorTransaction s b
$creturn :: forall s a. a -> CursorTransaction s a
return :: forall a. a -> CursorTransaction s a
Monad)

-- |
-- Cursor reference.
newtype Cursor s
  = Cursor ByteString

-- |
-- Given a template and encoded params produces a cursor,
-- while automating its resource management.
declareCursor :: ByteString -> G.EncodedParams -> CursorTransaction s (Cursor s)
declareCursor :: forall s.
ByteString -> EncodedParams -> CursorTransaction s (Cursor s)
declareCursor ByteString
template (G.EncodedParams (Supplied Params input
encoder input
params)) =
  StateT (Int, Transaction ()) Transaction (Cursor s)
-> CursorTransaction s (Cursor s)
forall s result.
StateT (Int, Transaction ()) Transaction result
-> CursorTransaction s result
CursorTransaction
    (StateT (Int, Transaction ()) Transaction (Cursor s)
 -> CursorTransaction s (Cursor s))
-> StateT (Int, Transaction ()) Transaction (Cursor s)
-> CursorTransaction s (Cursor s)
forall a b. (a -> b) -> a -> b
$ do
      ByteString
name <- ((Int, Transaction ()) -> (ByteString, (Int, Transaction ())))
-> StateT (Int, Transaction ()) Transaction ByteString
forall (m :: * -> *) s a. Monad m => (s -> (a, s)) -> StateT s m a
state (((Int, Transaction ()) -> (ByteString, (Int, Transaction ())))
 -> StateT (Int, Transaction ()) Transaction ByteString)
-> ((Int, Transaction ()) -> (ByteString, (Int, Transaction ())))
-> StateT (Int, Transaction ()) Transaction ByteString
forall a b. (a -> b) -> a -> b
$ do
        (Int
inc, Transaction ()
finaliser) <- (Int, Transaction ()) -> (Int, Transaction ())
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id
        ByteString
name <- ByteString -> (Int, Transaction ()) -> ByteString
forall a. a -> (Int, Transaction ()) -> a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> ByteString
forall {a}. Integral a => a -> ByteString
incToName Int
inc)
        Transaction ()
newFinaliser <- Transaction () -> (Int, Transaction ()) -> Transaction ()
forall a. a -> (Int, Transaction ()) -> a
forall (m :: * -> *) a. Monad m => a -> m a
return (Transaction ()
finaliser Transaction () -> Transaction () -> Transaction ()
forall a b. Transaction a -> Transaction b -> Transaction b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ByteString -> Transaction ()
C.closeCursor ByteString
name)
        (ByteString, (Int, Transaction ()))
-> (Int, Transaction ()) -> (ByteString, (Int, Transaction ()))
forall a. a -> (Int, Transaction ()) -> a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString
name, (Int -> Int
forall a. Enum a => a -> a
succ Int
inc, Transaction ()
newFinaliser))
      Transaction () -> StateT (Int, Transaction ()) Transaction ()
forall (m :: * -> *) a.
Monad m =>
m a -> StateT (Int, Transaction ()) m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (ByteString -> ByteString -> Params input -> input -> Transaction ()
forall params.
ByteString
-> ByteString -> Params params -> params -> Transaction ()
C.declareCursor ByteString
name ByteString
template Params input
encoder input
params)
      Cursor s -> StateT (Int, Transaction ()) Transaction (Cursor s)
forall a. a -> StateT (Int, Transaction ()) Transaction a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> Cursor s
forall s. ByteString -> Cursor s
Cursor ByteString
name)
  where
    incToName :: a -> ByteString
incToName a
inc =
      Builder -> ByteString
E.toByteString
        (Builder -> ByteString) -> Builder -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> Builder
E.byteString ByteString
"Hasql_CursorTransaction_"
        Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> a -> Builder
forall a. Integral a => a -> Builder
E.asciiIntegral a
inc

-- |
-- Fetch from a cursor a batch of the given size and decode it using the specified result decoder.
fetchBatch :: Cursor s -> G.BatchSize -> F.Result result -> CursorTransaction s result
fetchBatch :: forall s result.
Cursor s
-> BatchSize -> Result result -> CursorTransaction s result
fetchBatch (Cursor ByteString
name) BatchSize
batchSize Result result
decoder =
  Transaction result -> CursorTransaction s result
forall result s. Transaction result -> CursorTransaction s result
transaction (ByteString -> BatchSize -> Result result -> Transaction result
forall result.
ByteString -> BatchSize -> Result result -> Transaction result
C.fetchFromCursor ByteString
name BatchSize
batchSize Result result
decoder)

-- |
-- Lift a standard transaction.
-- Note that the transaction must not execute other CursorTransactions.
transaction :: A.Transaction result -> CursorTransaction s result
transaction :: forall result s. Transaction result -> CursorTransaction s result
transaction =
  StateT (Int, Transaction ()) Transaction result
-> CursorTransaction s result
forall s result.
StateT (Int, Transaction ()) Transaction result
-> CursorTransaction s result
CursorTransaction (StateT (Int, Transaction ()) Transaction result
 -> CursorTransaction s result)
-> (Transaction result
    -> StateT (Int, Transaction ()) Transaction result)
-> Transaction result
-> CursorTransaction s result
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Transaction result
-> StateT (Int, Transaction ()) Transaction result
forall (m :: * -> *) a.
Monad m =>
m a -> StateT (Int, Transaction ()) m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift

run :: (forall s. CursorTransaction s result) -> A.Transaction result
run :: forall result.
(forall s. CursorTransaction s result) -> Transaction result
run (CursorTransaction StateT (Int, Transaction ()) Transaction result
stack) =
  do
    (result
result, (Int
_, Transaction ()
finaliser)) <- StateT (Int, Transaction ()) Transaction result
-> (Int, Transaction ())
-> Transaction (result, (Int, Transaction ()))
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT StateT (Int, Transaction ()) Transaction result
stack (Int
1, () -> Transaction ()
forall a. a -> Transaction a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
    Transaction ()
finaliser
    result -> Transaction result
forall a. a -> Transaction a
forall (m :: * -> *) a. Monad m => a -> m a
return result
result