{-|
Module      : Mdbx.Database
Copyright   : (c) 2021 Francisco Vallarino
License     : BSD-3-Clause (see the LICENSE file)
Maintainer  : fjvallarino@gmail.com
Stability   : experimental
Portability : non-portable

High level API to create, update, delete and query an MDBX database.
-}
{-# LANGUAGE Strict #-}

module Mdbx.Database (
  -- * Get
  getItem,
  getItems,
  getRange,
  getRangePairs,
  getBounds,
  -- * Save
  putItem,
  putItems,
  -- * Delete
  delItem,
  delItems,
  delRange
) where

import Control.Applicative ((<|>))
import Control.Exception (SomeException(..), bracket, catch, throw)
import Control.Monad (forM, forM_, void, when)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Fail (MonadFail)
import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
import Data.Function (fix)
import Data.Maybe (catMaybes, fromJust, isJust)

import Mdbx.API
import Mdbx.Types

-- | Returns the value associated with the given key, if any.
getItem
  :: (MonadIO m, MonadFail m, MdbxItem k, MdbxItem v)
  => MdbxEnv       -- ^ The environment.
  -> MdbxDbi       -- ^ The database.
  -> k             -- ^ The key to lookup.
  -> m (Maybe v)   -- ^ The matching value, if any.
getItem :: MdbxEnv -> MdbxDbi -> k -> m (Maybe v)
getItem MdbxEnv
env MdbxDbi
dbi k
key = IO (Maybe v) -> m (Maybe v)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe v) -> m (Maybe v))
-> ((MdbxTxn -> IO (Maybe v)) -> IO (Maybe v))
-> (MdbxTxn -> IO (Maybe v))
-> m (Maybe v)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MdbxEnv -> (MdbxTxn -> IO (Maybe v)) -> IO (Maybe v)
forall a. MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInReadTxn MdbxEnv
env ((MdbxTxn -> IO (Maybe v)) -> m (Maybe v))
-> (MdbxTxn -> IO (Maybe v)) -> m (Maybe v)
forall a b. (a -> b) -> a -> b
$ \MdbxTxn
txn -> do
  k -> (MdbxVal -> IO (Maybe v)) -> IO (Maybe v)
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
key ((MdbxVal -> IO (Maybe v)) -> IO (Maybe v))
-> (MdbxVal -> IO (Maybe v)) -> IO (Maybe v)
forall a b. (a -> b) -> a -> b
$ \MdbxVal
mkey -> do
    Maybe MdbxVal
mval <- MdbxTxn -> MdbxDbi -> MdbxVal -> IO (Maybe MdbxVal)
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> m (Maybe MdbxVal)
itemGet MdbxTxn
txn MdbxDbi
dbi MdbxVal
mkey
    (MdbxVal -> IO v) -> Maybe MdbxVal -> IO (Maybe v)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM MdbxVal -> IO v
forall i. MdbxItem i => MdbxVal -> IO i
fromMdbxVal Maybe MdbxVal
mval

{-|
Returns the values associated to a list of keys. Returned length may not match
that of provided keys in case some of them are not found.
-}
getItems
  :: (MonadIO m, MonadFail m, MdbxItem k, MdbxItem v)
  => MdbxEnv       -- ^ The environment.
  -> MdbxDbi       -- ^ The database.
  -> [k]           -- ^ The keys to lookup.
  -> m [v]         -- ^ The matching values. Length may not match that of keys.
getItems :: MdbxEnv -> MdbxDbi -> [k] -> m [v]
getItems MdbxEnv
env MdbxDbi
dbi [k]
keys = IO [v] -> m [v]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [v] -> m [v])
-> ((MdbxTxn -> IO [v]) -> IO [v]) -> (MdbxTxn -> IO [v]) -> m [v]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MdbxEnv -> (MdbxTxn -> IO [v]) -> IO [v]
forall a. MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInReadTxn MdbxEnv
env ((MdbxTxn -> IO [v]) -> m [v]) -> (MdbxTxn -> IO [v]) -> m [v]
forall a b. (a -> b) -> a -> b
$ \MdbxTxn
txn -> do
  [Maybe v]
resp <- [k] -> (k -> IO (Maybe v)) -> IO [Maybe v]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [k]
keys ((k -> IO (Maybe v)) -> IO [Maybe v])
-> (k -> IO (Maybe v)) -> IO [Maybe v]
forall a b. (a -> b) -> a -> b
$ \k
key ->
    k -> (MdbxVal -> IO (Maybe v)) -> IO (Maybe v)
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
key ((MdbxVal -> IO (Maybe v)) -> IO (Maybe v))
-> (MdbxVal -> IO (Maybe v)) -> IO (Maybe v)
forall a b. (a -> b) -> a -> b
$ \MdbxVal
mkey -> do
      Maybe MdbxVal
mval <- MdbxTxn -> MdbxDbi -> MdbxVal -> IO (Maybe MdbxVal)
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> m (Maybe MdbxVal)
itemGet MdbxTxn
txn MdbxDbi
dbi MdbxVal
mkey
      (MdbxVal -> IO v) -> Maybe MdbxVal -> IO (Maybe v)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM MdbxVal -> IO v
forall i. MdbxItem i => MdbxVal -> IO i
fromMdbxVal Maybe MdbxVal
mval

  [v] -> IO [v]
forall (m :: * -> *) a. Monad m => a -> m a
return ([v] -> IO [v]) -> [v] -> IO [v]
forall a b. (a -> b) -> a -> b
$ [Maybe v] -> [v]
forall a. [Maybe a] -> [a]
catMaybes [Maybe v]
resp

-- | Returns the list of values whose keys lie between the provided range.
getRange
  :: (MonadIO m, MonadFail m, MdbxItem k, MdbxItem v)
  => MdbxEnv       -- ^ The environment.
  -> MdbxDbi       -- ^ The database.
  -> k             -- ^ The start of the range (inclusive).
  -> k             -- ^ The end of the range (inclusive).
  -> m [v]         -- ^ The matching values.
getRange :: MdbxEnv -> MdbxDbi -> k -> k -> m [v]
getRange MdbxEnv
env MdbxDbi
dbi k
start k
end = IO [v] -> m [v]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [v] -> m [v])
-> ((MdbxTxn -> IO [v]) -> IO [v]) -> (MdbxTxn -> IO [v]) -> m [v]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MdbxEnv -> (MdbxTxn -> IO [v]) -> IO [v]
forall a. MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInReadTxn MdbxEnv
env ((MdbxTxn -> IO [v]) -> m [v]) -> (MdbxTxn -> IO [v]) -> m [v]
forall a b. (a -> b) -> a -> b
$ \MdbxTxn
txn -> do
  MdbxTxn -> MdbxDbi -> (MdbxCursor -> IO [v]) -> IO [v]
forall a. MdbxTxn -> MdbxDbi -> (MdbxCursor -> IO a) -> IO a
doInCursor MdbxTxn
txn MdbxDbi
dbi ((MdbxCursor -> IO [v]) -> IO [v])
-> (MdbxCursor -> IO [v]) -> IO [v]
forall a b. (a -> b) -> a -> b
$ \MdbxCursor
cursor ->
    k -> (MdbxVal -> IO [v]) -> IO [v]
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
start ((MdbxVal -> IO [v]) -> IO [v]) -> (MdbxVal -> IO [v]) -> IO [v]
forall a b. (a -> b) -> a -> b
$ \MdbxVal
skey ->
      k -> (MdbxVal -> IO [v]) -> IO [v]
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
end ((MdbxVal -> IO [v]) -> IO [v]) -> (MdbxVal -> IO [v]) -> IO [v]
forall a b. (a -> b) -> a -> b
$ \MdbxVal
ekey -> do
        Maybe (MdbxVal, MdbxVal)
pair1 <- MdbxCursor -> MdbxVal -> IO (Maybe (MdbxVal, MdbxVal))
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxCursor -> MdbxVal -> m (Maybe (MdbxVal, MdbxVal))
cursorRange MdbxCursor
cursor MdbxVal
skey
        ((((Maybe (MdbxVal, MdbxVal), [v]) -> IO [v])
  -> (Maybe (MdbxVal, MdbxVal), [v]) -> IO [v])
 -> (Maybe (MdbxVal, MdbxVal), [v]) -> IO [v])
-> (Maybe (MdbxVal, MdbxVal), [v])
-> (((Maybe (MdbxVal, MdbxVal), [v]) -> IO [v])
    -> (Maybe (MdbxVal, MdbxVal), [v]) -> IO [v])
-> IO [v]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (((Maybe (MdbxVal, MdbxVal), [v]) -> IO [v])
 -> (Maybe (MdbxVal, MdbxVal), [v]) -> IO [v])
-> (Maybe (MdbxVal, MdbxVal), [v]) -> IO [v]
forall a. (a -> a) -> a
fix (Maybe (MdbxVal, MdbxVal)
pair1, []) ((((Maybe (MdbxVal, MdbxVal), [v]) -> IO [v])
  -> (Maybe (MdbxVal, MdbxVal), [v]) -> IO [v])
 -> IO [v])
-> (((Maybe (MdbxVal, MdbxVal), [v]) -> IO [v])
    -> (Maybe (MdbxVal, MdbxVal), [v]) -> IO [v])
-> IO [v]
forall a b. (a -> b) -> a -> b
$ \(Maybe (MdbxVal, MdbxVal), [v]) -> IO [v]
loop (Maybe (MdbxVal, MdbxVal)
pair, [v]
items) -> do
          Bool
isValid <- MdbxTxn
-> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> IO Bool
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> m Bool
pairLEKey MdbxTxn
txn MdbxDbi
dbi MdbxVal
ekey Maybe (MdbxVal, MdbxVal)
pair

          if Bool
isValid
            then do
              v
val <- MdbxVal -> IO v
forall i. MdbxItem i => MdbxVal -> IO i
fromMdbxVal (MdbxVal -> IO v)
-> (Maybe (MdbxVal, MdbxVal) -> MdbxVal)
-> Maybe (MdbxVal, MdbxVal)
-> IO v
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MdbxVal, MdbxVal) -> MdbxVal
forall a b. (a, b) -> b
snd ((MdbxVal, MdbxVal) -> MdbxVal)
-> (Maybe (MdbxVal, MdbxVal) -> (MdbxVal, MdbxVal))
-> Maybe (MdbxVal, MdbxVal)
-> MdbxVal
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (MdbxVal, MdbxVal) -> (MdbxVal, MdbxVal)
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (MdbxVal, MdbxVal) -> IO v)
-> Maybe (MdbxVal, MdbxVal) -> IO v
forall a b. (a -> b) -> a -> b
$ Maybe (MdbxVal, MdbxVal)
pair
              Maybe (MdbxVal, MdbxVal)
newPair <- MdbxCursor -> IO (Maybe (MdbxVal, MdbxVal))
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxCursor -> m (Maybe (MdbxVal, MdbxVal))
cursorNext MdbxCursor
cursor

              (Maybe (MdbxVal, MdbxVal), [v]) -> IO [v]
loop (Maybe (MdbxVal, MdbxVal)
newPair, v
val v -> [v] -> [v]
forall a. a -> [a] -> [a]
: [v]
items)
            else [v] -> IO [v]
forall (m :: * -> *) a. Monad m => a -> m a
return ([v] -> [v]
forall a. [a] -> [a]
reverse [v]
items)

{-|
Returns the list of key/value pairs whose keys lie between the provided range.
-}
getRangePairs
  :: (MonadIO m, MonadFail m, MdbxItem k, MdbxItem v)
  => MdbxEnv       -- ^ The environment.
  -> MdbxDbi       -- ^ The database.
  -> k             -- ^ The start of the range (inclusive).
  -> k             -- ^ The end of the range (inclusive).
  -> m [(k, v)]    -- ^ The matching pairs.
getRangePairs :: MdbxEnv -> MdbxDbi -> k -> k -> m [(k, v)]
getRangePairs MdbxEnv
env MdbxDbi
dbi k
start k
end = IO [(k, v)] -> m [(k, v)]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [(k, v)] -> m [(k, v)])
-> ((MdbxTxn -> IO [(k, v)]) -> IO [(k, v)])
-> (MdbxTxn -> IO [(k, v)])
-> m [(k, v)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MdbxEnv -> (MdbxTxn -> IO [(k, v)]) -> IO [(k, v)]
forall a. MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInReadTxn MdbxEnv
env ((MdbxTxn -> IO [(k, v)]) -> m [(k, v)])
-> (MdbxTxn -> IO [(k, v)]) -> m [(k, v)]
forall a b. (a -> b) -> a -> b
$ \MdbxTxn
txn ->
  MdbxTxn -> MdbxDbi -> (MdbxCursor -> IO [(k, v)]) -> IO [(k, v)]
forall a. MdbxTxn -> MdbxDbi -> (MdbxCursor -> IO a) -> IO a
doInCursor MdbxTxn
txn MdbxDbi
dbi ((MdbxCursor -> IO [(k, v)]) -> IO [(k, v)])
-> (MdbxCursor -> IO [(k, v)]) -> IO [(k, v)]
forall a b. (a -> b) -> a -> b
$ \MdbxCursor
cursor ->
    k -> (MdbxVal -> IO [(k, v)]) -> IO [(k, v)]
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
start ((MdbxVal -> IO [(k, v)]) -> IO [(k, v)])
-> (MdbxVal -> IO [(k, v)]) -> IO [(k, v)]
forall a b. (a -> b) -> a -> b
$ \MdbxVal
skey ->
      k -> (MdbxVal -> IO [(k, v)]) -> IO [(k, v)]
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
end ((MdbxVal -> IO [(k, v)]) -> IO [(k, v)])
-> (MdbxVal -> IO [(k, v)]) -> IO [(k, v)]
forall a b. (a -> b) -> a -> b
$ \MdbxVal
ekey -> do
        Maybe (MdbxVal, MdbxVal)
pair1 <- MdbxCursor -> MdbxVal -> IO (Maybe (MdbxVal, MdbxVal))
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxCursor -> MdbxVal -> m (Maybe (MdbxVal, MdbxVal))
cursorRange MdbxCursor
cursor MdbxVal
skey
        ((((Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)])
  -> (Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)])
 -> (Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)])
-> (Maybe (MdbxVal, MdbxVal), [(k, v)])
-> (((Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)])
    -> (Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)])
-> IO [(k, v)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (((Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)])
 -> (Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)])
-> (Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)]
forall a. (a -> a) -> a
fix (Maybe (MdbxVal, MdbxVal)
pair1, []) ((((Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)])
  -> (Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)])
 -> IO [(k, v)])
-> (((Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)])
    -> (Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)])
-> IO [(k, v)]
forall a b. (a -> b) -> a -> b
$ \(Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)]
loop (Maybe (MdbxVal, MdbxVal)
pair, [(k, v)]
items) -> do
          Bool
isValid <- MdbxTxn
-> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> IO Bool
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> m Bool
pairLEKey MdbxTxn
txn MdbxDbi
dbi MdbxVal
ekey Maybe (MdbxVal, MdbxVal)
pair

          if Bool
isValid
            then do
              k
key <- MdbxVal -> IO k
forall i. MdbxItem i => MdbxVal -> IO i
fromMdbxVal (MdbxVal -> IO k)
-> (Maybe (MdbxVal, MdbxVal) -> MdbxVal)
-> Maybe (MdbxVal, MdbxVal)
-> IO k
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MdbxVal, MdbxVal) -> MdbxVal
forall a b. (a, b) -> a
fst ((MdbxVal, MdbxVal) -> MdbxVal)
-> (Maybe (MdbxVal, MdbxVal) -> (MdbxVal, MdbxVal))
-> Maybe (MdbxVal, MdbxVal)
-> MdbxVal
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (MdbxVal, MdbxVal) -> (MdbxVal, MdbxVal)
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (MdbxVal, MdbxVal) -> IO k)
-> Maybe (MdbxVal, MdbxVal) -> IO k
forall a b. (a -> b) -> a -> b
$ Maybe (MdbxVal, MdbxVal)
pair
              v
val <- MdbxVal -> IO v
forall i. MdbxItem i => MdbxVal -> IO i
fromMdbxVal (MdbxVal -> IO v)
-> (Maybe (MdbxVal, MdbxVal) -> MdbxVal)
-> Maybe (MdbxVal, MdbxVal)
-> IO v
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MdbxVal, MdbxVal) -> MdbxVal
forall a b. (a, b) -> b
snd ((MdbxVal, MdbxVal) -> MdbxVal)
-> (Maybe (MdbxVal, MdbxVal) -> (MdbxVal, MdbxVal))
-> Maybe (MdbxVal, MdbxVal)
-> MdbxVal
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (MdbxVal, MdbxVal) -> (MdbxVal, MdbxVal)
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (MdbxVal, MdbxVal) -> IO v)
-> Maybe (MdbxVal, MdbxVal) -> IO v
forall a b. (a -> b) -> a -> b
$ Maybe (MdbxVal, MdbxVal)
pair

              Maybe (MdbxVal, MdbxVal)
newPair <- MdbxCursor -> IO (Maybe (MdbxVal, MdbxVal))
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxCursor -> m (Maybe (MdbxVal, MdbxVal))
cursorNext MdbxCursor
cursor

              (Maybe (MdbxVal, MdbxVal), [(k, v)]) -> IO [(k, v)]
loop (Maybe (MdbxVal, MdbxVal)
newPair, (k
key, v
val) (k, v) -> [(k, v)] -> [(k, v)]
forall a. a -> [a] -> [a]
: [(k, v)]
items)
            else [(k, v)] -> IO [(k, v)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([(k, v)] -> [(k, v)]
forall a. [a] -> [a]
reverse [(k, v)]
items)

{-|
Returns the minimum and maximum keys, and their respective values, between the
provided key range.

Both start and end keys are inclusive, thus the same key/value pairs will be
returned if they exist. Otherwise, the next\/previous valid key\/value pairs
will be returned respectively.
-}
getBounds
  :: (MonadIO m, MonadFail m, MdbxItem k, MdbxItem v)
  => MdbxEnv                       -- ^ The environment.
  -> MdbxDbi                       -- ^ The database.
  -> k                             -- ^ The start of the range (inclusive).
  -> k                             -- ^ The end of the range (inclusive).
  -> m (Maybe ((k, v), (k, v)))    -- ^ The bounding pairs, if any.
getBounds :: MdbxEnv -> MdbxDbi -> k -> k -> m (Maybe ((k, v), (k, v)))
getBounds MdbxEnv
env MdbxDbi
dbi k
start k
end = IO (Maybe ((k, v), (k, v))) -> m (Maybe ((k, v), (k, v)))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe ((k, v), (k, v))) -> m (Maybe ((k, v), (k, v))))
-> ((MdbxTxn -> IO (Maybe ((k, v), (k, v))))
    -> IO (Maybe ((k, v), (k, v))))
-> (MdbxTxn -> IO (Maybe ((k, v), (k, v))))
-> m (Maybe ((k, v), (k, v)))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MdbxEnv
-> (MdbxTxn -> IO (Maybe ((k, v), (k, v))))
-> IO (Maybe ((k, v), (k, v)))
forall a. MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInReadTxn MdbxEnv
env ((MdbxTxn -> IO (Maybe ((k, v), (k, v))))
 -> m (Maybe ((k, v), (k, v))))
-> (MdbxTxn -> IO (Maybe ((k, v), (k, v))))
-> m (Maybe ((k, v), (k, v)))
forall a b. (a -> b) -> a -> b
$ \MdbxTxn
txn -> do
  MdbxTxn
-> MdbxDbi
-> (MdbxCursor -> IO (Maybe ((k, v), (k, v))))
-> IO (Maybe ((k, v), (k, v)))
forall a. MdbxTxn -> MdbxDbi -> (MdbxCursor -> IO a) -> IO a
doInCursor MdbxTxn
txn MdbxDbi
dbi ((MdbxCursor -> IO (Maybe ((k, v), (k, v))))
 -> IO (Maybe ((k, v), (k, v))))
-> (MdbxCursor -> IO (Maybe ((k, v), (k, v))))
-> IO (Maybe ((k, v), (k, v)))
forall a b. (a -> b) -> a -> b
$ \MdbxCursor
cursor ->
    k
-> (MdbxVal -> IO (Maybe ((k, v), (k, v))))
-> IO (Maybe ((k, v), (k, v)))
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
start ((MdbxVal -> IO (Maybe ((k, v), (k, v))))
 -> IO (Maybe ((k, v), (k, v))))
-> (MdbxVal -> IO (Maybe ((k, v), (k, v))))
-> IO (Maybe ((k, v), (k, v)))
forall a b. (a -> b) -> a -> b
$ \MdbxVal
skey ->
      k
-> (MdbxVal -> IO (Maybe ((k, v), (k, v))))
-> IO (Maybe ((k, v), (k, v)))
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
end ((MdbxVal -> IO (Maybe ((k, v), (k, v))))
 -> IO (Maybe ((k, v), (k, v))))
-> (MdbxVal -> IO (Maybe ((k, v), (k, v))))
-> IO (Maybe ((k, v), (k, v)))
forall a b. (a -> b) -> a -> b
$ \MdbxVal
ekey -> do
        Maybe (MdbxVal, MdbxVal)
pairMem1 <- MdbxCursor -> MdbxVal -> IO (Maybe (MdbxVal, MdbxVal))
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxCursor -> MdbxVal -> m (Maybe (MdbxVal, MdbxVal))
cursorRange MdbxCursor
cursor MdbxVal
skey
        Bool
isValid1 <- MdbxTxn
-> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> IO Bool
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> m Bool
pairLEKey MdbxTxn
txn MdbxDbi
dbi MdbxVal
ekey Maybe (MdbxVal, MdbxVal)
pairMem1
        Maybe (k, v)
pair1 <- Bool -> Maybe (MdbxVal, MdbxVal) -> IO (Maybe (k, v))
forall a a.
(MdbxItem a, MdbxItem a) =>
Bool -> Maybe (MdbxVal, MdbxVal) -> IO (Maybe (a, a))
fetchIfValid Bool
isValid1 Maybe (MdbxVal, MdbxVal)
pairMem1

        Maybe (MdbxVal, MdbxVal)
pairMem2 <- MaybeT IO (MdbxVal, MdbxVal) -> IO (Maybe (MdbxVal, MdbxVal))
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT IO (MdbxVal, MdbxVal) -> IO (Maybe (MdbxVal, MdbxVal)))
-> MaybeT IO (MdbxVal, MdbxVal) -> IO (Maybe (MdbxVal, MdbxVal))
forall a b. (a -> b) -> a -> b
$ IO (Maybe (MdbxVal, MdbxVal)) -> MaybeT IO (MdbxVal, MdbxVal)
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (MdbxCursor -> MdbxVal -> IO (Maybe (MdbxVal, MdbxVal))
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxCursor -> MdbxVal -> m (Maybe (MdbxVal, MdbxVal))
cursorAt MdbxCursor
cursor MdbxVal
ekey) MaybeT IO (MdbxVal, MdbxVal)
-> MaybeT IO (MdbxVal, MdbxVal) -> MaybeT IO (MdbxVal, MdbxVal)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> IO (Maybe (MdbxVal, MdbxVal)) -> MaybeT IO (MdbxVal, MdbxVal)
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (MdbxCursor -> IO (Maybe (MdbxVal, MdbxVal))
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxCursor -> m (Maybe (MdbxVal, MdbxVal))
cursorPrev MdbxCursor
cursor)
        Bool
isValid2 <- MdbxTxn
-> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> IO Bool
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> m Bool
pairGEKey MdbxTxn
txn MdbxDbi
dbi MdbxVal
skey Maybe (MdbxVal, MdbxVal)
pairMem2
        Maybe (k, v)
pair2 <- Bool -> Maybe (MdbxVal, MdbxVal) -> IO (Maybe (k, v))
forall a a.
(MdbxItem a, MdbxItem a) =>
Bool -> Maybe (MdbxVal, MdbxVal) -> IO (Maybe (a, a))
fetchIfValid Bool
isValid2 Maybe (MdbxVal, MdbxVal)
pairMem2

        Maybe ((k, v), (k, v)) -> IO (Maybe ((k, v), (k, v)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ((k, v), (k, v)) -> IO (Maybe ((k, v), (k, v))))
-> Maybe ((k, v), (k, v)) -> IO (Maybe ((k, v), (k, v)))
forall a b. (a -> b) -> a -> b
$ (,) ((k, v) -> (k, v) -> ((k, v), (k, v)))
-> Maybe (k, v) -> Maybe ((k, v) -> ((k, v), (k, v)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (k, v)
pair1 Maybe ((k, v) -> ((k, v), (k, v)))
-> Maybe (k, v) -> Maybe ((k, v), (k, v))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe (k, v)
pair2
  where
    fromMdbxPairs :: (MdbxVal, MdbxVal) -> IO (a, a)
fromMdbxPairs (MdbxVal
mkey, MdbxVal
mval) = (,) (a -> a -> (a, a)) -> IO a -> IO (a -> (a, a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MdbxVal -> IO a
forall i. MdbxItem i => MdbxVal -> IO i
fromMdbxVal MdbxVal
mkey IO (a -> (a, a)) -> IO a -> IO (a, a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> MdbxVal -> IO a
forall i. MdbxItem i => MdbxVal -> IO i
fromMdbxVal MdbxVal
mval
    fetchIfValid :: Bool -> Maybe (MdbxVal, MdbxVal) -> IO (Maybe (a, a))
fetchIfValid Bool
True Maybe (MdbxVal, MdbxVal)
pairMem = ((MdbxVal, MdbxVal) -> IO (a, a))
-> Maybe (MdbxVal, MdbxVal) -> IO (Maybe (a, a))
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (MdbxVal, MdbxVal) -> IO (a, a)
forall a a.
(MdbxItem a, MdbxItem a) =>
(MdbxVal, MdbxVal) -> IO (a, a)
fromMdbxPairs Maybe (MdbxVal, MdbxVal)
pairMem
    fetchIfValid Bool
_ Maybe (MdbxVal, MdbxVal)
_ = Maybe (a, a) -> IO (Maybe (a, a))
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (a, a)
forall a. Maybe a
Nothing

-- | Saves the given key/value pair.
putItem
  :: (MonadIO m, MonadFail m, MdbxItem k, MdbxItem v)
  => MdbxEnv       -- ^ The environment.
  -> MdbxDbi       -- ^ The database.
  -> k             -- ^ The key.
  -> v             -- ^ The value.
  -> m ()
putItem :: MdbxEnv -> MdbxDbi -> k -> v -> m ()
putItem MdbxEnv
env MdbxDbi
dbi k
key v
item =
  IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ())
-> ((MdbxTxn -> IO ()) -> IO ()) -> (MdbxTxn -> IO ()) -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MdbxEnv -> (MdbxTxn -> IO ()) -> IO ()
forall a. MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInWriteTxn MdbxEnv
env ((MdbxTxn -> IO ()) -> m ()) -> (MdbxTxn -> IO ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \MdbxTxn
txn ->
    k -> (MdbxVal -> IO ()) -> IO ()
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
key ((MdbxVal -> IO ()) -> IO ()) -> (MdbxVal -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \MdbxVal
mkey ->
      v -> (MdbxVal -> IO ()) -> IO ()
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal v
item ((MdbxVal -> IO ()) -> IO ()) -> (MdbxVal -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \MdbxVal
mitem ->
        MdbxTxn -> MdbxDbi -> MdbxVal -> MdbxVal -> [MdbxPutFlags] -> IO ()
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> MdbxVal -> [MdbxPutFlags] -> m ()
itemPut MdbxTxn
txn MdbxDbi
dbi MdbxVal
mkey MdbxVal
mitem []

-- | Saves the given key/value pairs. Runs in a single transaction.
putItems
  :: (MonadIO m, MonadFail m, MdbxItem k, MdbxItem v)
  => MdbxEnv       -- ^ The environment.
  -> MdbxDbi       -- ^ The database.
  -> [(k, v)]      -- ^ The list of key/value pairs.
  -> m ()
putItems :: MdbxEnv -> MdbxDbi -> [(k, v)] -> m ()
putItems MdbxEnv
env MdbxDbi
dbi [(k, v)]
items =
  IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ())
-> ((MdbxTxn -> IO ()) -> IO ()) -> (MdbxTxn -> IO ()) -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MdbxEnv -> (MdbxTxn -> IO ()) -> IO ()
forall a. MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInWriteTxn MdbxEnv
env ((MdbxTxn -> IO ()) -> m ()) -> (MdbxTxn -> IO ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \MdbxTxn
txn ->
    [(k, v)] -> ((k, v) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(k, v)]
items (((k, v) -> IO ()) -> IO ()) -> ((k, v) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(k
key, v
item) ->
      k -> (MdbxVal -> IO ()) -> IO ()
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
key ((MdbxVal -> IO ()) -> IO ()) -> (MdbxVal -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \MdbxVal
mkey ->
        v -> (MdbxVal -> IO ()) -> IO ()
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal v
item ((MdbxVal -> IO ()) -> IO ()) -> (MdbxVal -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \MdbxVal
mitem ->
          MdbxTxn -> MdbxDbi -> MdbxVal -> MdbxVal -> [MdbxPutFlags] -> IO ()
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> MdbxVal -> [MdbxPutFlags] -> m ()
itemPut MdbxTxn
txn MdbxDbi
dbi MdbxVal
mkey MdbxVal
mitem []

-- | Deletes the item associated with the given key, if any.
delItem
  :: (MonadIO m, MonadFail m, MdbxItem k)
  => MdbxEnv       -- ^ The environment.
  -> MdbxDbi       -- ^ The database.
  -> k             -- ^ The key to delete.
  -> m ()
delItem :: MdbxEnv -> MdbxDbi -> k -> m ()
delItem MdbxEnv
env MdbxDbi
dbi k
key =
  IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ())
-> ((MdbxTxn -> IO ()) -> IO ()) -> (MdbxTxn -> IO ()) -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MdbxEnv -> (MdbxTxn -> IO ()) -> IO ()
forall a. MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInWriteTxn MdbxEnv
env ((MdbxTxn -> IO ()) -> m ()) -> (MdbxTxn -> IO ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \MdbxTxn
txn ->
    IO () -> IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ k -> (MdbxVal -> IO ()) -> IO ()
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
key ((MdbxVal -> IO ()) -> IO ()) -> (MdbxVal -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \MdbxVal
mkey ->
      MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe MdbxVal -> IO ()
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe MdbxVal -> m ()
itemDel MdbxTxn
txn MdbxDbi
dbi MdbxVal
mkey Maybe MdbxVal
forall a. Maybe a
Nothing

{-|
Deletes the items associated with the given keys, if any. Runs in a single
transaction.
-}
delItems
  :: (MonadIO m, MonadFail m, MdbxItem k)
  => MdbxEnv       -- ^ The environment.
  -> MdbxDbi       -- ^ The database.
  -> [k]           -- ^ The keys to delete.
  -> m ()
delItems :: MdbxEnv -> MdbxDbi -> [k] -> m ()
delItems MdbxEnv
env MdbxDbi
dbi [k]
keys =
  IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ())
-> ((MdbxTxn -> IO ()) -> IO ()) -> (MdbxTxn -> IO ()) -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MdbxEnv -> (MdbxTxn -> IO ()) -> IO ()
forall a. MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInWriteTxn MdbxEnv
env ((MdbxTxn -> IO ()) -> m ()) -> (MdbxTxn -> IO ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \MdbxTxn
txn ->
    [k] -> (k -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [k]
keys ((k -> IO ()) -> IO ()) -> (k -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \k
key ->
      k -> (MdbxVal -> IO ()) -> IO ()
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
key ((MdbxVal -> IO ()) -> IO ()) -> (MdbxVal -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \MdbxVal
mkey ->
        MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe MdbxVal -> IO ()
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe MdbxVal -> m ()
itemDel MdbxTxn
txn MdbxDbi
dbi MdbxVal
mkey Maybe MdbxVal
forall a. Maybe a
Nothing

-- | Deletes the values whose keys lie between the provided range.
delRange
  :: (MonadIO m, MonadFail m, MdbxItem k)
  => MdbxEnv       -- ^ The environment.
  -> MdbxDbi       -- ^ The database.
  -> k             -- ^ The start of the range (inclusive).
  -> k             -- ^ The end of the range (inclusive).
  -> m ()
delRange :: MdbxEnv -> MdbxDbi -> k -> k -> m ()
delRange MdbxEnv
env MdbxDbi
dbi k
start k
end =
  IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ())
-> ((MdbxTxn -> IO ()) -> IO ()) -> (MdbxTxn -> IO ()) -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MdbxEnv -> (MdbxTxn -> IO ()) -> IO ()
forall a. MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInWriteTxn MdbxEnv
env ((MdbxTxn -> IO ()) -> m ()) -> (MdbxTxn -> IO ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \MdbxTxn
txn -> do
    MdbxTxn -> MdbxDbi -> (MdbxCursor -> IO ()) -> IO ()
forall a. MdbxTxn -> MdbxDbi -> (MdbxCursor -> IO a) -> IO a
doInCursor MdbxTxn
txn MdbxDbi
dbi ((MdbxCursor -> IO ()) -> IO ()) -> (MdbxCursor -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \MdbxCursor
cursor ->
      k -> (MdbxVal -> IO ()) -> IO ()
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
start ((MdbxVal -> IO ()) -> IO ()) -> (MdbxVal -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \MdbxVal
skey ->
        k -> (MdbxVal -> IO ()) -> IO ()
forall i b. MdbxItem i => i -> (MdbxVal -> IO b) -> IO b
toMdbxVal k
end ((MdbxVal -> IO ()) -> IO ()) -> (MdbxVal -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \MdbxVal
ekey -> do
          Maybe (MdbxVal, MdbxVal)
pair1 <- MdbxCursor -> MdbxVal -> IO (Maybe (MdbxVal, MdbxVal))
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxCursor -> MdbxVal -> m (Maybe (MdbxVal, MdbxVal))
cursorRange MdbxCursor
cursor MdbxVal
skey
          (((Maybe (MdbxVal, MdbxVal) -> IO ())
  -> Maybe (MdbxVal, MdbxVal) -> IO ())
 -> Maybe (MdbxVal, MdbxVal) -> IO ())
-> Maybe (MdbxVal, MdbxVal)
-> ((Maybe (MdbxVal, MdbxVal) -> IO ())
    -> Maybe (MdbxVal, MdbxVal) -> IO ())
-> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((Maybe (MdbxVal, MdbxVal) -> IO ())
 -> Maybe (MdbxVal, MdbxVal) -> IO ())
-> Maybe (MdbxVal, MdbxVal) -> IO ()
forall a. (a -> a) -> a
fix Maybe (MdbxVal, MdbxVal)
pair1 (((Maybe (MdbxVal, MdbxVal) -> IO ())
  -> Maybe (MdbxVal, MdbxVal) -> IO ())
 -> IO ())
-> ((Maybe (MdbxVal, MdbxVal) -> IO ())
    -> Maybe (MdbxVal, MdbxVal) -> IO ())
-> IO ()
forall a b. (a -> b) -> a -> b
$ \Maybe (MdbxVal, MdbxVal) -> IO ()
loop Maybe (MdbxVal, MdbxVal)
pair -> do
            Bool
isValid <- MdbxTxn
-> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> IO Bool
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> m Bool
pairLEKey MdbxTxn
txn MdbxDbi
dbi MdbxVal
ekey Maybe (MdbxVal, MdbxVal)
pair

            Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isValid (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
              let mkey :: MdbxVal
mkey = (MdbxVal, MdbxVal) -> MdbxVal
forall a b. (a, b) -> a
fst ((MdbxVal, MdbxVal) -> MdbxVal)
-> (Maybe (MdbxVal, MdbxVal) -> (MdbxVal, MdbxVal))
-> Maybe (MdbxVal, MdbxVal)
-> MdbxVal
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (MdbxVal, MdbxVal) -> (MdbxVal, MdbxVal)
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (MdbxVal, MdbxVal) -> MdbxVal)
-> Maybe (MdbxVal, MdbxVal) -> MdbxVal
forall a b. (a -> b) -> a -> b
$ Maybe (MdbxVal, MdbxVal)
pair
              MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe MdbxVal -> IO ()
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe MdbxVal -> m ()
itemDel MdbxTxn
txn MdbxDbi
dbi MdbxVal
mkey Maybe MdbxVal
forall a. Maybe a
Nothing
              Maybe (MdbxVal, MdbxVal)
newPair <- MdbxCursor -> IO (Maybe (MdbxVal, MdbxVal))
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxCursor -> m (Maybe (MdbxVal, MdbxVal))
cursorNext MdbxCursor
cursor

              Maybe (MdbxVal, MdbxVal) -> IO ()
loop Maybe (MdbxVal, MdbxVal)
newPair

-- Helpers

{-|
Checks if the key of the key/value pair is lower or equal than the provided key.
-}
pairLEKey
  :: (MonadIO m, MonadFail m)
  => MdbxTxn       -- ^ The active transaction.
  -> MdbxDbi       -- ^ The database.
  -> MdbxVal       -- ^ The reference key.
  -> Maybe (MdbxVal, MdbxVal)  -- ^ The key/value pair to check
  -> m Bool        -- ^ True if the key/value is lower or equal than the key.
pairLEKey :: MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> m Bool
pairLEKey MdbxTxn
txn MdbxDbi
dbi MdbxVal
end Maybe (MdbxVal, MdbxVal)
Nothing = Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
pairLEKey MdbxTxn
txn MdbxDbi
dbi MdbxVal
end (Just (MdbxVal
key, MdbxVal
_)) = (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0) (Int -> Bool) -> m Int -> m Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MdbxTxn -> MdbxDbi -> MdbxVal -> MdbxVal -> m Int
forall (m :: * -> *).
MonadIO m =>
MdbxTxn -> MdbxDbi -> MdbxVal -> MdbxVal -> m Int
keyCmp MdbxTxn
txn MdbxDbi
dbi MdbxVal
key MdbxVal
end

{-|
Checks if the key of the key/value pair is greater or equal than the provided
key.
-}
pairGEKey
  :: (MonadIO m, MonadFail m)
  => MdbxTxn       -- ^ The active transaction.
  -> MdbxDbi       -- ^ The database.
  -> MdbxVal       -- ^ The reference key.
  -> Maybe (MdbxVal, MdbxVal)  -- ^ The key/value pair to check
  -> m Bool        -- ^ True if the key/value is greater or equal than the key.
pairGEKey :: MdbxTxn -> MdbxDbi -> MdbxVal -> Maybe (MdbxVal, MdbxVal) -> m Bool
pairGEKey MdbxTxn
txn MdbxDbi
dbi MdbxVal
end Maybe (MdbxVal, MdbxVal)
Nothing = Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
pairGEKey MdbxTxn
txn MdbxDbi
dbi MdbxVal
end (Just (MdbxVal
key, MdbxVal
_)) = (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0) (Int -> Bool) -> m Int -> m Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MdbxTxn -> MdbxDbi -> MdbxVal -> MdbxVal -> m Int
forall (m :: * -> *).
MonadIO m =>
MdbxTxn -> MdbxDbi -> MdbxVal -> MdbxVal -> m Int
keyCmp MdbxTxn
txn MdbxDbi
dbi MdbxVal
key MdbxVal
end

-- | Runs the given action in a read only transaction.
doInReadTxn
  :: MdbxEnv
  -> (MdbxTxn -> IO a)
  -> IO a
doInReadTxn :: MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInReadTxn MdbxEnv
env MdbxTxn -> IO a
action = MdbxEnv
-> Maybe MdbxTxn -> [MdbxTxnFlags] -> (MdbxTxn -> IO a) -> IO a
forall a.
MdbxEnv
-> Maybe MdbxTxn -> [MdbxTxnFlags] -> (MdbxTxn -> IO a) -> IO a
doInTxn MdbxEnv
env Maybe MdbxTxn
forall a. Maybe a
Nothing [MdbxTxnFlags
MdbxTxnRdonly] MdbxTxn -> IO a
action

{-|
Runs the given action in a read/write transaction, that will be aborted if an
exception is thrown and committed otherwise.
-}
doInWriteTxn
  :: MdbxEnv
  -> (MdbxTxn -> IO a)
  -> IO a
doInWriteTxn :: MdbxEnv -> (MdbxTxn -> IO a) -> IO a
doInWriteTxn MdbxEnv
env MdbxTxn -> IO a
action = MdbxEnv
-> Maybe MdbxTxn -> [MdbxTxnFlags] -> (MdbxTxn -> IO a) -> IO a
forall a.
MdbxEnv
-> Maybe MdbxTxn -> [MdbxTxnFlags] -> (MdbxTxn -> IO a) -> IO a
doInTxn MdbxEnv
env Maybe MdbxTxn
forall a. Maybe a
Nothing [] MdbxTxn -> IO a
action

{-|
Runs the given action in a transaction with the specified flags and, optionally,
parent transaction. The transaction will be aborted if an exception is thrown,
committed otherwise.
-}
doInTxn
  :: MdbxEnv
  -> Maybe MdbxTxn
  -> [MdbxTxnFlags]
  -> (MdbxTxn -> IO a)
  -> IO a
doInTxn :: MdbxEnv
-> Maybe MdbxTxn -> [MdbxTxnFlags] -> (MdbxTxn -> IO a) -> IO a
doInTxn MdbxEnv
env Maybe MdbxTxn
parentTxn [MdbxTxnFlags]
flags MdbxTxn -> IO a
action = do
  MdbxTxn
txn <- MdbxEnv -> Maybe MdbxTxn -> [MdbxTxnFlags] -> IO MdbxTxn
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxEnv -> Maybe MdbxTxn -> [MdbxTxnFlags] -> m MdbxTxn
txnBegin MdbxEnv
env Maybe MdbxTxn
parentTxn [MdbxTxnFlags]
flags
  (SomeException -> IO a) -> IO a -> IO a
forall a. (SomeException -> IO a) -> IO a -> IO a
handleAny (MdbxTxn -> SomeException -> IO a
forall (m :: * -> *) e b.
(MonadIO m, MonadFail m, Exception e) =>
MdbxTxn -> e -> m b
handleEx MdbxTxn
txn) (IO a -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$ do
    a
res <- MdbxTxn -> IO a
action MdbxTxn
txn
    MdbxTxn -> IO ()
forall (m :: * -> *). (MonadIO m, MonadFail m) => MdbxTxn -> m ()
txnCommit MdbxTxn
txn
    a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
res
  where
    handleEx :: MdbxTxn -> e -> m b
handleEx MdbxTxn
txn e
e = MdbxTxn -> m ()
forall (m :: * -> *). (MonadIO m, MonadFail m) => MdbxTxn -> m ()
txnAbort MdbxTxn
txn m () -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> e -> m b
forall a e. Exception e => e -> a
throw e
e

{-|
Runs the given action with an open cursor which will be closed when finished or
on error.
-}
doInCursor
  :: MdbxTxn
  -> MdbxDbi
  -> (MdbxCursor -> IO a)
  -> IO a
doInCursor :: MdbxTxn -> MdbxDbi -> (MdbxCursor -> IO a) -> IO a
doInCursor MdbxTxn
txn MdbxDbi
dbi MdbxCursor -> IO a
action = IO MdbxCursor
-> (MdbxCursor -> IO ()) -> (MdbxCursor -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (MdbxTxn -> MdbxDbi -> IO MdbxCursor
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxTxn -> MdbxDbi -> m MdbxCursor
cursorOpen MdbxTxn
txn MdbxDbi
dbi) MdbxCursor -> IO ()
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
MdbxCursor -> m ()
cursorClose MdbxCursor -> IO a
action

handleAny :: (SomeException -> IO a) -> IO a -> IO a
handleAny :: (SomeException -> IO a) -> IO a -> IO a
handleAny SomeException -> IO a
action IO a
handler = IO a -> (SomeException -> IO a) -> IO a
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch IO a
handler SomeException -> IO a
action