module Database.LMDB.Simple.Extra
(
null
, size
, member
, notMember
, lookup
, findWithDefault
, insert
, insertWith
, insertWithKey
, insertLookupWithKey
, delete
, adjust
, adjustWithKey
, update
, updateWithKey
, updateLookupWithKey
, alter
, foldr
, foldl
, foldrWithKey
, foldlWithKey
, foldDatabaseWithKey
, elems
, keys
, toList
) where
import Prelude hiding
( foldl
, foldr
, lookup
, null
)
import Control.Monad
( void
)
import Data.Maybe
( fromMaybe
, isJust
)
import Database.LMDB.Raw
( MDB_stat (ms_entries)
, MDB_val
, MDB_cursor_op (MDB_SET)
, MDB_cursor'
, MDB_WriteFlags
, mdb_stat'
, mdb_cursor_get'
, mdb_cursor_put'
, mdb_cursor_del'
)
import Database.LMDB.Simple.Internal
( ReadWrite
, Transaction (Txn)
, Database (Db)
, Serialise
, forEachForward
, forEachReverse
, marshalOut
, peekVal
, withCursor
, defaultWriteFlags
, overwriteFlags
)
import qualified Database.LMDB.Simple.Internal as Internal
import Foreign
( alloca
, nullPtr
, with
)
lookup :: (Serialise k, Serialise v)
=> k -> Database k v -> Transaction mode (Maybe v)
lookup = flip Internal.get
findWithDefault :: (Serialise k, Serialise v)
=> v -> k -> Database k v -> Transaction mode v
findWithDefault def key db = fromMaybe def <$> lookup key db
null :: Database k v -> Transaction mode Bool
null (Db _ dbi) = Txn $ \txn -> do
stat <- mdb_stat' txn dbi
return (ms_entries stat == 0)
size :: Database k v -> Transaction mode Int
size (Db _ dbi) = Txn $ \txn -> do
stat <- mdb_stat' txn dbi
return (fromIntegral $ ms_entries stat)
member :: Serialise k => k -> Database k v -> Transaction mode Bool
member key db = isJust <$> Internal.get' db key
notMember :: Serialise k => k -> Database k v -> Transaction mode Bool
notMember key db = not <$> member key db
insert :: (Serialise k, Serialise v)
=> k -> v -> Database k v -> Transaction ReadWrite ()
insert key value db = Internal.put db key value
insertWith :: (Serialise k, Serialise v)
=> (v -> v -> v) -> k -> v -> Database k v -> Transaction ReadWrite ()
insertWith f = insertWithKey (const f)
insertWithKey :: (Serialise k, Serialise v)
=> (k -> v -> v -> v) -> k -> v -> Database k v
-> Transaction ReadWrite ()
insertWithKey f key value = void . insertLookupWithKey f key value
insertLookupWithKey :: (Serialise k, Serialise v)
=> (k -> v -> v -> v) -> k -> v -> Database k v
-> Transaction ReadWrite (Maybe v)
insertLookupWithKey f key value (Db _ dbi) = Txn $ \txn ->
withCursor txn dbi $ \cursor -> marshalOut key $ \kval ->
with kval $ \kptr -> alloca $ \vptr -> do
found <- mdb_cursor_get' MDB_SET cursor kptr vptr
if found
then do oldValue <- peekVal vptr
cursorPut cursor overwriteFlags kval (f key value oldValue)
return (Just oldValue)
else do cursorPut cursor defaultWriteFlags kval value
return Nothing
where cursorPut :: Serialise v
=> MDB_cursor' -> MDB_WriteFlags -> MDB_val -> v -> IO Bool
cursorPut cursor writeFlags kval value = marshalOut value $ \vval ->
mdb_cursor_put' writeFlags cursor kval vval
elems :: Serialise v => Database k v -> Transaction mode [v]
elems = foldr (:) []
keys :: Serialise k => Database k v -> Transaction mode [k]
keys (Db _ dbi) = Txn $ \txn ->
alloca $ \kptr ->
forEachForward txn dbi kptr nullPtr [] $ \rest ->
(:) <$> peekVal kptr <*> rest
toList :: (Serialise k, Serialise v) => Database k v -> Transaction mode [(k, v)]
toList = foldrWithKey (\k v -> ((k, v) :)) []
foldr :: Serialise v => (v -> b -> b) -> b -> Database k v -> Transaction mode b
foldr f z (Db _ dbi) = Txn $ \txn ->
alloca $ \vptr ->
forEachForward txn dbi nullPtr vptr z $ \rest ->
f <$> peekVal vptr <*> rest
foldrWithKey :: (Serialise k, Serialise v)
=> (k -> v -> b -> b) -> b -> Database k v -> Transaction mode b
foldrWithKey f z (Db _ dbi) = Txn $ \txn ->
alloca $ \kptr ->
alloca $ \vptr ->
forEachForward txn dbi kptr vptr z $ \rest ->
f <$> peekVal kptr <*> peekVal vptr <*> rest
foldl :: Serialise v => (a -> v -> a) -> a -> Database k v -> Transaction mode a
foldl f z (Db _ dbi) = Txn $ \txn ->
alloca $ \vptr ->
forEachReverse txn dbi nullPtr vptr z $ \rest ->
flip f <$> peekVal vptr <*> rest
foldlWithKey :: (Serialise k, Serialise v)
=> (a -> k -> v -> a) -> a -> Database k v -> Transaction mode a
foldlWithKey f z (Db _ dbi) = Txn $ \txn ->
alloca $ \kptr ->
alloca $ \vptr ->
forEachReverse txn dbi kptr vptr z $ \rest ->
(\k v a -> f a k v) <$> peekVal kptr <*> peekVal vptr <*> rest
foldDatabaseWithKey :: (Monoid m, Serialise k, Serialise v)
=> (k -> v -> m) -> Database k v -> Transaction mode m
foldDatabaseWithKey f = foldrWithKey (\k v a -> f k v `mappend` a) mempty
delete :: Serialise k => k -> Database k v -> Transaction ReadWrite Bool
delete = flip Internal.delete
adjust :: (Serialise k, Serialise v)
=> (v -> v) -> k -> Database k v -> Transaction ReadWrite Bool
adjust f = adjustWithKey (const f)
adjustWithKey :: (Serialise k, Serialise v)
=> (k -> v -> v) -> k -> Database k v -> Transaction ReadWrite Bool
adjustWithKey f = updateWithKey (\k v -> Just $ f k v)
update :: (Serialise k, Serialise v)
=> (v -> Maybe v) -> k -> Database k v -> Transaction ReadWrite Bool
update f = updateWithKey (const f)
updateWithKey :: (Serialise k, Serialise v)
=> (k -> v -> Maybe v) -> k -> Database k v
-> Transaction ReadWrite Bool
updateWithKey f key db = isJust <$> updateLookupWithKey f key db
updateLookupWithKey :: (Serialise k, Serialise v)
=> (k -> v -> Maybe v) -> k -> Database k v
-> Transaction ReadWrite (Maybe v)
updateLookupWithKey f = alterWithKey (maybe Nothing . f)
alter :: (Serialise k, Serialise v)
=> (Maybe v -> Maybe v) -> k -> Database k v -> Transaction ReadWrite ()
alter f key db = void $ alterWithKey (const f) key db
alterWithKey :: (Serialise k, Serialise v)
=> (k -> Maybe v -> Maybe v) -> k -> Database k v
-> Transaction ReadWrite (Maybe v)
alterWithKey f key (Db _ dbi) = Txn $ \txn ->
withCursor txn dbi $ \cursor -> marshalOut key $ \kval ->
with kval $ \kptr -> alloca $ \vptr -> do
found <- mdb_cursor_get' MDB_SET cursor kptr vptr
if found
then peekVal vptr >>= \oldValue -> do
let old = Just oldValue
case f key old of
new@(Just newValue) -> marshalOut newValue $ \vval ->
mdb_cursor_put' overwriteFlags cursor kval vval >>
return new
Nothing -> mdb_cursor_del' defaultWriteFlags cursor >>
return old
else case f key Nothing of
new@(Just newValue) -> marshalOut newValue $ \vval ->
mdb_cursor_put' defaultWriteFlags cursor kval vval >>
return new
Nothing -> return Nothing