packages feed

hasbolt 0.1.2.1 → 0.1.3.0

raw patch · 8 files changed

+74/−190 lines, 8 filesdep +connectiondep −QuickCheckdep −hasboltdep −hspecdep ~containersdep ~networkPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: connection

Dependencies removed: QuickCheck, hasbolt, hspec

Dependency ranges changed: containers, network

API changes (from Hackage documentation)

+ Database.Bolt: Structure :: Word8 -> [Value] -> Structure
+ Database.Bolt: [fields] :: Structure -> [Value]
+ Database.Bolt: [secure] :: BoltCfg -> Bool
+ Database.Bolt: [signature] :: Structure -> Word8
+ Database.Bolt: data Structure
+ Database.Bolt.Lazy: Structure :: Word8 -> [Value] -> Structure
+ Database.Bolt.Lazy: [fields] :: Structure -> [Value]
+ Database.Bolt.Lazy: [secure] :: BoltCfg -> Bool
+ Database.Bolt.Lazy: [signature] :: Structure -> Word8
+ Database.Bolt.Lazy: data Structure
- Database.Bolt: BoltCfg :: Word32 -> Word32 -> Text -> Word16 -> Int -> String -> Int -> Text -> Text -> BoltCfg
+ Database.Bolt: BoltCfg :: Word32 -> Word32 -> Text -> Word16 -> Int -> String -> Int -> Text -> Text -> Bool -> BoltCfg
- Database.Bolt.Lazy: BoltCfg :: Word32 -> Word32 -> Text -> Word16 -> Int -> String -> Int -> Text -> Text -> BoltCfg
+ Database.Bolt.Lazy: BoltCfg :: Word32 -> Word32 -> Text -> Word16 -> Int -> String -> Int -> Text -> Text -> Bool -> BoltCfg

Files

hasbolt.cabal view
@@ -1,10 +1,10 @@ name: hasbolt-version: 0.1.2.1+version: 0.1.3.0 cabal-version: >=1.10 build-type: Simple license: BSD3 license-file: LICENSE-copyright: Copyright: (c) 2016 Pavel Yakovlev+copyright: (c) 2016 Pavel Yakovlev maintainer: pavel@yakovlev.me homepage: https://github.com/zmactep/hasbolt#readme synopsis: Haskell driver for Neo4j 3+ (BOLT protocol)@@ -42,6 +42,7 @@         data-binary-ieee754 >=0.4.4 && <0.5,         transformers >=0.5.2.0 && <0.6,         network >=2.6.3.1 && <2.7,+        connection >=0.2.8 && <0.3,         data-default >=0.7.1.1 && <0.8,         hex >=0.1.2 && <0.2     default-language: Haskell2010@@ -51,26 +52,11 @@         Database.Bolt.Value.Helpers         Database.Bolt.Value.Instances         Database.Bolt.Value.Structure-        Database.Bolt.Connection.Socket+        Database.Bolt.Connection.Connection         Database.Bolt.Connection.Type         Database.Bolt.Connection.Instances         Database.Bolt.Connection.Pipe         Database.Bolt.Connection         Database.Bolt.Record-    ghc-options: -Wall -O2+    ghc-options: -Wall -test-suite hasbolt-test-    type: exitcode-stdio-1.0-    main-is: Spec.hs-    build-depends:-        base >=4.8 && <5,-        hasbolt >=0.1.2.1 && <0.2,-        hspec >=2.4.1 && <2.5,-        QuickCheck >=2.9 && <2.11,-        hex >=0.1.2 && <0.2,-        text >=1.2.2.1 && <1.3,-        containers >=0.5.7.1 && <0.6,-        bytestring >=0.10.8.1 && <0.11-    default-language: Haskell2010-    hs-source-dirs: test-    ghc-options: -threaded -rtsopts -with-rtsopts=-N
src/Database/Bolt.hs view
@@ -4,7 +4,7 @@     , run, queryP, query, queryP_, query_     , Pipe     , BoltCfg (..)-    , BoltValue (..), Value (..), Record, RecordValue (..), at+    , BoltValue (..), Value (..), Structure (..), Record, RecordValue (..), at     , Node (..), Relationship (..), URelationship (..), Path (..)     ) where 
+ src/Database/Bolt/Connection/Connection.hs view
@@ -0,0 +1,37 @@+module Database.Bolt.Connection.Connection where++import           Control.Monad          (when, forM_)+import           Control.Monad.IO.Class (MonadIO (..))+import           Data.ByteString        (ByteString, null)+import           Data.Default           (Default (..))+import           Network.Socket         (PortNumber)+import           Network.Connection     (Connection, ConnectionParams (..), connectTo, connectionSetSecure,+                                         initConnectionContext, connectionClose, connectionGetExact, connectionPut)+import           Prelude                hiding (null)++connect :: MonadIO m => Bool -> String -> PortNumber -> m Connection+connect secure host port = do ctx <- liftIO $ initConnectionContext+                              conn <- liftIO $ connectTo ctx $ ConnectionParams { connectionHostname  = host+                                                                                , connectionPort      = port+                                                                                , connectionUseSecure = Nothing+                                                                                , connectionUseSocks  = Nothing+                                                                                }+                              when secure $+                                liftIO $ connectionSetSecure ctx conn def+                              pure conn++close :: MonadIO m => Connection -> m ()+close = liftIO . connectionClose++recv :: MonadIO m => Connection -> Int -> m (Maybe ByteString)+recv conn = liftIO . (filterMaybe (not . null) <$>) . connectionGetExact conn+  where+    filterMaybe :: (a -> Bool) -> a -> Maybe a+    filterMaybe p x | p x       = Just x+                    | otherwise = Nothing++send :: MonadIO m => Connection -> ByteString -> m ()+send conn = liftIO . connectionPut conn++sendMany :: MonadIO m => Connection -> [ByteString] -> m ()+sendMany conn chunks = forM_ chunks $ send conn
src/Database/Bolt/Connection/Pipe.hs view
@@ -4,28 +4,27 @@ import           Database.Bolt.Connection.Type import           Database.Bolt.Value.Instances import           Database.Bolt.Value.Type--import           Database.Bolt.Connection.Socket    (Socket, closeSock,-                                                     connectSock, recv, send,-                                                     sendMany)+import qualified Database.Bolt.Connection.Connection as C (close, connect, recv,+                                                           send, sendMany) -import           Control.Monad                      (forM_, unless, void, when)-import           Control.Monad.IO.Class             (MonadIO (..))-import           Data.ByteString                    (ByteString)-import qualified Data.ByteString                    as B (concat, length, null,-                                                          splitAt)-import           Data.Word                          (Word16)+import           Control.Monad                       (forM_, unless, void, when)+import           Control.Monad.IO.Class              (MonadIO (..))+import           Data.ByteString                     (ByteString)+import qualified Data.ByteString                     as B (concat, length, null,+                                                           splitAt)+import           Data.Word                           (Word16)+import           Network.Connection                  (Connection)  -- |Creates new 'Pipe' instance to use all requests through connect :: MonadIO m => BoltCfg -> m Pipe-connect bcfg = do (sock, _) <- connectSock (host bcfg) (show $ port bcfg)-                  let pipe = Pipe sock (maxChunkSize bcfg)+connect bcfg = do conn <- C.connect (secure bcfg) (host bcfg) (fromIntegral $ port bcfg)+                  let pipe = Pipe conn (maxChunkSize bcfg)                   handshake pipe bcfg                   pure pipe  -- |Closes 'Pipe' close :: MonadIO m => Pipe -> m ()-close = closeSock . connectionSocket+close = C.close . connection  -- |Resets current sessions reset :: MonadIO m => Pipe -> m ()@@ -42,13 +41,13 @@ discardAll pipe = flush pipe RequestDiscardAll >> void (fetch pipe)  flush :: MonadIO m => Pipe -> Request -> m ()-flush pipe request = do forM_ chunks $ sendMany sock . mkChunk-                        send sock terminal+flush pipe request = do forM_ chunks $ C.sendMany conn . mkChunk+                        C.send conn terminal   where bs        = pack $ toStructure request         chunkSize = chunkSizeFor (mcs pipe) bs         chunks    = split chunkSize bs         terminal  = encodeStrict (0 :: Word16)-        sock      = connectionSocket pipe+        conn      = connection pipe          mkChunk :: ByteString -> [ByteString]         mkChunk chunk = let size = fromIntegral (B.length chunk) :: Word16@@ -57,11 +56,11 @@ fetch :: MonadIO m => Pipe -> m Response fetch pipe = do bs <- B.concat <$> chunks                 unpack bs >>= fromStructure-  where sock = connectionSocket pipe+  where conn = connection pipe          chunks :: MonadIO m => m [ByteString]-        chunks = do size <- decodeStrict <$> recvChunk sock 2-                    chunk <- recvChunk sock size+        chunks = do size <- decodeStrict <$> recvChunk conn 2+                    chunk <- recvChunk conn size                     if B.null chunk                       then pure []                       else do rest <- chunks@@ -70,10 +69,10 @@ -- Helper functions  handshake :: MonadIO m => Pipe -> BoltCfg -> m ()-handshake pipe bcfg = do let sock = connectionSocket pipe-                         send sock (encodeStrict $ magic bcfg)-                         send sock (boltVersionProposal bcfg)-                         serverVersion <- decodeStrict <$> recvChunk sock 4+handshake pipe bcfg = do let conn = connection pipe+                         C.send conn (encodeStrict $ magic bcfg)+                         C.send conn (boltVersionProposal bcfg)+                         serverVersion <- decodeStrict <$> recvChunk conn 4                          when (serverVersion /= version bcfg) $                            fail "Unsupported server version"                          flush pipe (createInit bcfg)@@ -85,11 +84,11 @@ boltVersionProposal :: BoltCfg -> ByteString boltVersionProposal bcfg = B.concat $ encodeStrict <$> [version bcfg, 0, 0, 0] -recvChunk :: MonadIO m => Socket -> Word16 -> m ByteString-recvChunk sock size = B.concat <$> helper (fromIntegral size)+recvChunk :: MonadIO m => Connection -> Word16 -> m ByteString+recvChunk conn size = B.concat <$> helper (fromIntegral size)   where helper :: MonadIO m => Int -> m [ByteString]         helper 0  = pure []-        helper sz = do mbChunk <- recv sock sz+        helper sz = do mbChunk <- C.recv conn sz                        case mbChunk of                          Just chunk -> (chunk:) <$> helper (sz - B.length chunk)                          Nothing    -> fail "Cannot read chunk from sock"
− src/Database/Bolt/Connection/Socket.hs
@@ -1,46 +0,0 @@-module Database.Bolt.Connection.Socket-  ( Socket-  , connectSock, closeSock-  , recv, send, sendMany-  ) where--import           Control.Exception         (bracketOnError)-import           Control.Monad.IO.Class    (MonadIO (..))-import           Data.ByteString           (ByteString, null)-import           Network.Socket            (AddrInfoFlag (..), HostName,-                                            ServiceName, SockAddr, Socket,-                                            SocketType (..), addrAddress,-                                            addrFamily, addrFlags, addrProtocol,-                                            addrSocketType, defaultHints,-                                            getAddrInfo, socket, close, connect)-import qualified Network.Socket.ByteString as NSB (recv, sendAll, sendMany)-import           Prelude                   hiding (null)--connectSock :: MonadIO m => HostName -> ServiceName -> m (Socket, SockAddr)-connectSock host port = liftIO $ bracketOnError (createSock host port) (closeSock . fst) $-                          \(sock, addr) -> liftIO (connect sock addr) >> pure (sock, addr)--createSock :: MonadIO m => HostName -> ServiceName -> m (Socket, SockAddr)-createSock host port = liftIO $ do (addr:_) <- getAddrInfo (Just hints) (Just host) (Just port)-                                   let family'   = addrFamily addr-                                   let type'     = addrSocketType addr-                                   let protocol' = addrProtocol addr-                                   sock <- socket family' type' protocol'-                                   pure (sock, addrAddress addr)-  where hints = defaultHints { addrFlags = [AI_ADDRCONFIG]-                             , addrSocketType = Stream-                             }--closeSock :: MonadIO m => Socket -> m ()-closeSock = liftIO . close--recv :: MonadIO m => Socket -> Int -> m (Maybe ByteString)-recv sock nbytes = liftIO $ do bs <- NSB.recv sock nbytes-                               if null bs then pure Nothing-                                            else pure (Just bs)--send :: MonadIO m => Socket -> ByteString -> m ()-send sock = liftIO . NSB.sendAll sock--sendMany :: MonadIO m => Socket -> [ByteString] -> m ()-sendMany sock = liftIO . NSB.sendMany sock
src/Database/Bolt/Connection/Type.hs view
@@ -4,12 +4,11 @@  import           Database.Bolt.Value.Type -import           Database.Bolt.Connection.Socket (Socket)- import           Data.Default                    (Default (..)) import           Data.Map.Strict                 (Map) import           Data.Text                       (Text) import           Data.Word                       (Word16, Word32)+import           Network.Connection              (Connection)  -- |Configuration of driver connection data BoltCfg = BoltCfg { magic         :: Word32  -- ^'6060B017' value@@ -21,6 +20,7 @@                        , port          :: Int     -- ^Neo4j server port                        , user          :: Text    -- ^Neo4j user                        , password      :: Text    -- ^Neo4j password+                       , secure        :: Bool    -- ^Use TLS or not                        }  instance Default BoltCfg where@@ -33,10 +33,11 @@                 , port          = 7687                 , user          = ""                 , password      = ""+                , secure        = False                 } -data Pipe = Pipe { connectionSocket :: Socket     -- ^Driver connection socket-                 , mcs              :: Word16     -- ^Driver maximum chunk size of request+data Pipe = Pipe { connection :: Connection -- ^Driver connection socket+                 , mcs        :: Word16     -- ^Driver maximum chunk size of request                  }  data AuthToken = AuthToken { scheme      :: Text
src/Database/Bolt/Lazy.hs view
@@ -4,7 +4,7 @@     , run, queryP, query, queryP_, query_     , Pipe     , BoltCfg (..)-    , BoltValue (..), Value (..), Record, RecordValue (..), at+    , BoltValue (..), Value (..), Structure (..), Record, RecordValue (..), at     , Node (..), Relationship (..), URelationship (..), Path (..)     ) where 
− test/Spec.hs
@@ -1,93 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--import           Control.Applicative      ((<$>))-import           Data.ByteString          (ByteString)-import           Data.ByteString.Lazy     (fromStrict, toStrict)-import           Data.Hex-import           Data.Map                 (Map (..))-import qualified Data.Map                 as M (empty, fromList)-import           Data.Text                (Text)-import qualified Data.Text                as T (pack)-import           Test.Hspec-import           Test.QuickCheck--import Database.Bolt--main :: IO ()-main = hspec $ do-         packStreamTests-         unpackStreamTests--unpackStreamTests :: Spec-unpackStreamTests =-  describe "Unpack" $ do-    it "unpacks integers correct" $ do-      u1 <- prepareData "01" >>= unpack :: IO Int-      u1 `shouldBe` 1-      u42 <- prepareData "2A" >>= unpack :: IO Int-      u42 `shouldBe` 42-      u1234 <- prepareData "C904D2" >>= unpack :: IO Int-      u1234 `shouldBe` 1234-    it "unpacks doubles correct" $ do-      u6d <- prepareData "C1401921FB54442D18" >>= unpack :: IO Double-      u6d `shouldBe` 6.283185307179586-      um1d <- prepareData "C1BFF199999999999A" >>= unpack :: IO Double-      um1d `shouldBe` (-1.1)-    it "unpacks booleans correct" $ do-      uF <- prepareData "C2" >>= unpack :: IO Bool-      uF `shouldBe` False-      uT <- prepareData "C3" >>= unpack :: IO Bool-      uT `shouldBe` True-    it "unpacks strings correct" $ do-      usE <- prepareData "80" >>= unpack :: IO Text-      usE `shouldBe` T.pack ""-      usA <- prepareData "8141" >>= unpack :: IO Text-      usA `shouldBe` T.pack "A"-      usU <- prepareData "D0124772C3B6C39F656E6D61C39F7374C3A46265" >>= unpack :: IO Text-      usU `shouldBe` T.pack "Größenmaßstäbe"-    it "unpacks lists correct" $ do-      ulE <- prepareData "90" >>= unpack :: IO [Int]-      ulE `shouldBe` []-      ulI <- prepareData "93010203" >>= unpack :: IO [Int]-      ulI `shouldBe` [1,2,3]-      ulL <- prepareData "D4280102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728" >>= unpack :: IO [Int]-      ulL `shouldBe` [1..40]-    it "unpacks dicts correct" $ do-      udE <- prepareData "A0" >>= unpack :: IO (Map Text ())-      udE `shouldBe` M.fromList []-      udS <- prepareData "A1836F6E658465696E73" >>= unpack :: IO (Map Text Text)-      udS `shouldBe` M.fromList [(T.pack "one", T.pack "eins")]-    it "unpacks () correct" $ do-      uN <- prepareData "C0" >>= unpack :: IO ()-      uN `shouldBe` ()--packStreamTests :: Spec-packStreamTests =-  describe "Pack" $ do-    it "packs integers correct" $ do-      hex (pack (1::Int)) `shouldBe` "01"-      hex (pack (42::Int)) `shouldBe` "2A"-      hex (pack (1234::Int)) `shouldBe` "C904D2"-    it "packs doubles correct" $ do-      hex (pack (6.283185307179586::Double)) `shouldBe` "C1401921FB54442D18"-      hex (pack (-1.1::Double)) `shouldBe` "C1BFF199999999999A"-    it "packs booleans correct" $ do-      hex (pack False) `shouldBe` "C2"-      hex (pack True) `shouldBe` "C3"-    it "packs strings correct" $ do-      hex (pack $ T.pack "") `shouldBe` "80"-      hex (pack $ T.pack "A") `shouldBe` "8141"-      hex (pack $ T.pack "Größenmaßstäbe") `shouldBe` "D0124772C3B6C39F656E6D61C39F7374C3A46265"-      hex (pack $ T.pack "ABCDEFGHIJKLMNOPQRSTUVWXYZ") `shouldBe` "D01A4142434445464748494A4B4C4D4E4F505152535455565758595A"-    it "packs lists correct" $ do-      hex (pack ([]::[Int])) `shouldBe` "90"-      hex (pack ([1,2,3]::[Int])) `shouldBe` "93010203"-      hex (pack ([1..40]::[Int])) `shouldBe` "D4280102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728"-    it "packs dicts correct" $ do-      hex (pack (M.empty :: Map Text ())) `shouldBe` "A0"-      hex (pack (M.fromList [(T.pack "one", T.pack "eins")])) `shouldBe` "A1836F6E658465696E73"-    it "packs () correct" $-      hex (pack ()) `shouldBe` "C0"--prepareData :: Monad m => ByteString -> m ByteString-prepareData = (toStrict <$>) . unhex . fromStrict