higher-leveldb 0.3.0.1 → 0.3.1.0
raw patch · 3 files changed
+192/−3 lines, 3 filesdep ~data-defaultPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: data-default
API changes (from Hackage documentation)
- Database.LevelDB.Higher: instance (Control.Monad.Error.Class.MonadError e m, Database.LevelDB.Higher.MonadLevelDB m) => Database.LevelDB.Higher.MonadLevelDB (Control.Monad.Trans.Except.ExceptT e m)
+ Database.LevelDB.Higher: instance (GHC.Base.Monad m, Database.LevelDB.Higher.MonadLevelDB m) => Database.LevelDB.Higher.MonadLevelDB (Control.Monad.Trans.Except.ExceptT e m)
- Database.LevelDB.Higher: Options :: SrictNotUnpackedInt -> SrictNotUnpackedInt -> SrictNotUnpackedInt -> SrictNotUnpacked(Maybe Comparator) -> SrictNotUnpackedCompression -> SrictNotUnpackedBool -> SrictNotUnpackedBool -> SrictNotUnpackedInt -> SrictNotUnpackedBool -> SrictNotUnpackedInt -> SrictNotUnpacked(Maybe (Either BloomFilter FilterPolicy)) -> Options
+ Database.LevelDB.Higher: Options :: ~Int -> ~Int -> ~Int -> ~(Maybe Comparator) -> ~Compression -> ~Bool -> ~Bool -> ~Int -> ~Bool -> ~Int -> ~(Maybe (Either BloomFilter FilterPolicy)) -> Options
- Database.LevelDB.Higher: ReadOptions :: SrictNotUnpackedBool -> SrictNotUnpackedBool -> SrictNotUnpacked(Maybe Snapshot) -> ReadOptions
+ Database.LevelDB.Higher: ReadOptions :: ~Bool -> ~Bool -> ~(Maybe Snapshot) -> ReadOptions
- Database.LevelDB.Higher: WriteOptions :: SrictNotUnpackedBool -> WriteOptions
+ Database.LevelDB.Higher: WriteOptions :: ~Bool -> WriteOptions
- Database.LevelDB.Higher: [blockRestartInterval] :: Options -> SrictNotUnpackedInt
+ Database.LevelDB.Higher: [blockRestartInterval] :: Options -> ~Int
- Database.LevelDB.Higher: [blockSize] :: Options -> SrictNotUnpackedInt
+ Database.LevelDB.Higher: [blockSize] :: Options -> ~Int
- Database.LevelDB.Higher: [cacheSize] :: Options -> SrictNotUnpackedInt
+ Database.LevelDB.Higher: [cacheSize] :: Options -> ~Int
- Database.LevelDB.Higher: [comparator] :: Options -> SrictNotUnpacked(Maybe Comparator)
+ Database.LevelDB.Higher: [comparator] :: Options -> ~(Maybe Comparator)
- Database.LevelDB.Higher: [compression] :: Options -> SrictNotUnpackedCompression
+ Database.LevelDB.Higher: [compression] :: Options -> ~Compression
- Database.LevelDB.Higher: [createIfMissing] :: Options -> SrictNotUnpackedBool
+ Database.LevelDB.Higher: [createIfMissing] :: Options -> ~Bool
- Database.LevelDB.Higher: [errorIfExists] :: Options -> SrictNotUnpackedBool
+ Database.LevelDB.Higher: [errorIfExists] :: Options -> ~Bool
- Database.LevelDB.Higher: [fillCache] :: ReadOptions -> SrictNotUnpackedBool
+ Database.LevelDB.Higher: [fillCache] :: ReadOptions -> ~Bool
- Database.LevelDB.Higher: [filterPolicy] :: Options -> SrictNotUnpacked(Maybe (Either BloomFilter FilterPolicy))
+ Database.LevelDB.Higher: [filterPolicy] :: Options -> ~(Maybe (Either BloomFilter FilterPolicy))
- Database.LevelDB.Higher: [maxOpenFiles] :: Options -> SrictNotUnpackedInt
+ Database.LevelDB.Higher: [maxOpenFiles] :: Options -> ~Int
- Database.LevelDB.Higher: [paranoidChecks] :: Options -> SrictNotUnpackedBool
+ Database.LevelDB.Higher: [paranoidChecks] :: Options -> ~Bool
- Database.LevelDB.Higher: [sync] :: WriteOptions -> SrictNotUnpackedBool
+ Database.LevelDB.Higher: [sync] :: WriteOptions -> ~Bool
- Database.LevelDB.Higher: [useSnapshot] :: ReadOptions -> SrictNotUnpacked(Maybe Snapshot)
+ Database.LevelDB.Higher: [useSnapshot] :: ReadOptions -> ~(Maybe Snapshot)
- Database.LevelDB.Higher: [verifyCheckSums] :: ReadOptions -> SrictNotUnpackedBool
+ Database.LevelDB.Higher: [verifyCheckSums] :: ReadOptions -> ~Bool
- Database.LevelDB.Higher: [writeBufferSize] :: Options -> SrictNotUnpackedInt
+ Database.LevelDB.Higher: [writeBufferSize] :: Options -> ~Int
Files
- higher-leveldb.cabal +3/−2
- src/Database/LevelDB/Higher.hs +1/−1
- test/Database/LevelDB/HigherSpec.hs +188/−0
higher-leveldb.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: higher-leveldb-version: 0.3.0.1+version: 0.3.1.0 synopsis: A rich monadic API for working with leveldb databases. description: A rich monadic API for working with leveldb databases. homepage: https://github.com/jeremyjh/higher-leveldb@@ -34,12 +34,13 @@ , transformers-base >= 0.4.1 && < 0.5 , mtl >= 2.0 && < 2.3 , monad-control >= 0.3 && < 1.1- , data-default >= 0.5.1 && < 0.6+ , data-default >= 0.5.1 && < 0.8 , transformers >= 0.3 && < 0.6 test-suite spec ghc-options: -optl-Wl,-rpath,/usr/local/lib,-enable-new-dtags+ other-modules: Database.LevelDB.HigherSpec type: exitcode-stdio-1.0 hs-source-dirs: test main-is: Spec.hs
src/Database/LevelDB/Higher.hs view
@@ -218,7 +218,7 @@ INST(Monoid w, Strict.RWST r w s, Strict.mapRWST) #if MIN_VERSION_mtl(2,2,1)-INST(Except.MonadError e m, Except.ExceptT e, Except.mapExceptT)+INST(Monad m, Except.ExceptT e, Except.mapExceptT) #else INST(Error.Error e, Error.ErrorT e, Error.mapErrorT) #endif
+ test/Database/LevelDB/HigherSpec.hs view
@@ -0,0 +1,188 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Database.LevelDB.HigherSpec (main, spec) where++import qualified Data.ByteString as BS+import Data.Serialize (encode)+import Data.Monoid+import Test.Hspec+import System.Process(system)+import Database.LevelDB.Higher+import Control.Monad.Trans.Resource+import Control.Monad.Reader+import Control.Monad.Writer+import Control.Applicative (Applicative)+import Control.Monad.Base (MonadBase(..))+import Control.Concurrent.Lifted++--debug+import Debug.Trace+debug :: (Show a) => a -> a+debug a = traceShow a a+--debug+++main :: IO ()+main = hspec spec++setup :: IO ()+setup = system ("rm -rf " <> testDB) >> return ()++spec :: Spec+spec = do+ it "setup" $ setup >>= shouldReturn (return())+ describe "has a reader context API that" $ do+ it "can put" $ do+ withDBT $ put "putgetkey" "putgetvalue"+ `shouldReturn` ()+ it "can get" $ do+ withDBT $ get "putgetkey"+ `shouldReturn` (Just "putgetvalue")+ it "can delete" $ do+ withDBRT $ do+ put "deletekey" "doesn't matter"+ delete "deletekey"+ get "deletekey"+ `shouldReturn` Nothing+ it "can isolate data with keyspaces" $ do+ runCreateLevelDB testDB "thespace" $ do+ put "thekey" "thevalue"+ withKeySpace "otherspace" $ put "thekey" "othervalue"+ get "thekey"+ `shouldReturn` (Just "thevalue")+ it "can override read/write options locally" $ do+ withDBT $ do+ withOptions (def, def {sync = True}) $ do+ put "puttingsync" "can't you tell?"+ get "puttingsync"+ `shouldReturn` Just "can't you tell?"+ it "can scan and transform" $ do+ runCreateLevelDB testDB "scan" $ do+ put "employee:1" "Jill"+ put "employee:2" "Jack"+ put "cheeseburgers:1" "do not want"+ r1 <- scan "employee:" queryItems+ r2 <- scan "employee" $+ queryList {scanMap = \ (k, v) -> v <> " Smith"}+ r3 <- scan "e"+ queryItems { scanFilter = \ (_, v) -> v > "Jack" }+ r4 <- scan "employee" $+ queryBegins { scanInit = 0+ , scanMap = \ (_, v) -> BS.head v+ , scanFold = (+) }+ return (r1, r2, r3, r4)+ `shouldReturn` ( [("employee:1", "Jill"), ("employee:2", "Jack")]+ , [ "Jill Smith", "Jack Smith"]+ , [("employee:1", "Jill")]+ , 148)+ it "can write data in batches" $ do+ runLevelDB testDB dbOpts def "batches" $ do+ runBatch $ do+ putB "\1" "first"+ putB "\2" "second"+ putB "\3" "third"+ deleteB "\2"+ scan "" queryCount+ `shouldReturn` 2+ it "will do consistent reads in a snapshot" $ do+ runCreateLevelDB testDB "snapshot" $ do+ put "first" "initial value"+ withSnapshot $ do+ put "first" "don't see me"+ get "first"+ `shouldReturn` Just "initial value"+ describe "can be used in a custom MonadT stack" $ do+ it "can be used with a reader" $ do+ runTestAppR testDB "TestAppReader" $ do+ value <- ask+ put "thiskey" value+ get "thiskey"+ `shouldReturn` (Just "a string value to read")+ it "still works withKeySpace" $ do+ runTestAppR testDB "TestAppReader" $ do+ withKeySpace "TestAppReader2" $ do+ notit <- get "thiskey" -- not found in this keyspace+ gotit <- ask -- our top Reader still works+ return (notit, gotit)+ `shouldReturn` (Nothing, "a string value to read")+ it "can be used with a writer" $ do+ runTestAppW testDB "TestAppWriter" $ do+ put "writekey" "words"+ tell "tolja"+ withKeySpace "TestAppWriter2" $ do+ put "writekey" "not these words"+ tell "twice"+ get "writekey"+ `shouldReturn` (Just "words", "toljatwice")+ it "can work with a reader/writer" $ do+ runTestAppRW testDB "TestAppRW" $ do+ v <- ask+ put "writekey" v+ tell "toljer"+ get "writekey"+ `shouldReturn` (Just "a different string value to read"+ , "toljer")+ it "can get forked" $ do+ runTestAppR testDB "forkInReader" $ do+ put "onetwo" "three"+ forkTestAppR $ do+ rv <- ask+ threadDelay 1+ put "three" rv+ threadDelay 100+ get "three"+ `shouldReturn` Just "a string value to read"+ it "scans with a keyspace" $ do+ withDBT $ withKeySpace "overflow" $ do+ forM ([1..10] :: [Int]) $ \i -> do+ put (encode i) "hi guys"+ xs <- scan "" queryItems+ return $ length xs+ `shouldReturn` 10+++testDB = "/tmp/leveltest"+dbOpts = def {createIfMissing = True, cacheSize= 2048}++withDBT :: LevelDBT IO a -> IO a+withDBT = runLevelDB testDB dbOpts def "Database.LevelDB.HigherSpec"++withDBRT :: LevelDBT IO a -> IO a+withDBRT = runResourceT . runLevelDB' testDB dbOpts def "Database.LevelDB.HigherSpec"++runTestAppR :: FilePath -> KeySpace -> TestAppR a -> IO a+runTestAppR path ks ta = runLevelDB path dbOpts def ks $ do+ runReaderT (unTestAppR ta) "a string value to read"++runTestAppW :: FilePath -> KeySpace -> TestAppW a -> IO (a, BS.ByteString)+runTestAppW path ks ta = runLevelDB path dbOpts def ks $ do+ runWriterT (unTestAppW ta)++runTestAppRW :: FilePath -> KeySpace -> TestAppRW a -> IO (a, BS.ByteString)+runTestAppRW path ks ta = runLevelDB path dbOpts def ks $ do+ runWriterT $ runReaderT (unTestAppRW ta) "a different string value to read"++forkTestAppR :: TestAppR () -> TestAppR ThreadId+forkTestAppR ma = TestAppR $+ mapReaderT+ (\ld -> forkLevelDB ld)+ (unTestAppR ma)+++newtype TestAppR a = TestAppR { unTestAppR :: ReaderT BS.ByteString (LevelDBT IO) a}+ deriving ( Functor, Applicative, Monad, MonadBase IO+ , MonadReader BS.ByteString, MonadResource+ , MonadIO, MonadThrow, MonadLevelDB+ )++newtype TestAppW a = TestAppW { unTestAppW :: WriterT BS.ByteString (LevelDBT IO) a}+ deriving ( Functor, Applicative, Monad, MonadBase IO+ , MonadWriter BS.ByteString, MonadResource+ , MonadIO, MonadThrow, MonadLevelDB+ )+newtype TestAppRW a = TestAppRW { unTestAppRW :: ReaderT BS.ByteString+ (WriterT BS.ByteString (LevelDBT IO)) a}+ deriving ( Functor, Applicative, Monad, MonadBase IO+ , MonadReader BS.ByteString, MonadWriter BS.ByteString, MonadResource+ , MonadIO, MonadThrow, MonadLevelDB)