hascas 0.1.0.0 → 1.0.0
raw patch · 8 files changed
+382/−114 lines, 8 filesdep +safe-exceptionsdep ~base
Dependencies added: safe-exceptions
Dependency ranges changed: base
Files
- hascas.cabal +4/−2
- src/Batch.hs +2/−1
- src/CQL.hs +161/−8
- src/Common.hs +2/−1
- src/Derive.hs +5/−0
- src/Driver.hs +127/−33
- src/Query.hs +9/−2
- test/Spec.hs +72/−67
hascas.cabal view
@@ -1,7 +1,7 @@ name: hascas-version: 0.1.0.0+version: 1.0.0 synopsis: Cassandra driver for haskell-description: Please see README.md+description: This is a cassandra driver. homepage: https://github.com/eklavya/hascas#readme license: Apache license-file: LICENSE@@ -32,6 +32,7 @@ , stm , data-binary-ieee754 , mtl+ , safe-exceptions , template-haskell default-language: Haskell2010 @@ -50,6 +51,7 @@ , data-binary-ieee754 , hspec , mtl+ , safe-exceptions , template-haskell ghc-options: -threaded -rtsopts -with-rtsopts=-N default-language: Haskell2010
src/Batch.hs view
@@ -41,6 +41,7 @@ instance Batchable LoggedBatch where+ -- | Execute your batch query runBatch (LoggedBatch qs) = do (Candle driverQ) <- ask mvar <- liftIO newEmptyMVar@@ -48,7 +49,7 @@ liftIO $ atomically $ writeTBQueue driverQ (LongStr q, 13, mvar) res <- liftIO $ takeMVar mvar case res of- Left e -> throwError e+ Left e -> throwError e Right (RRows rows) -> return rows
src/CQL.hs view
@@ -1,9 +1,162 @@-module CQL (module X) where+{- |+Module : CQL+Description : Cassandra Driver+Copyright : (c) Saurabh Rawat, 2016+License : Apache+Maintainer : saurabh.rawat90@gmail.com -import Batch as X-import Codec as X-import Common as X-import Derive as X-import Driver as X-import Encoding as X-import Query as X+This is a cassandra driver. It currently has:++- Select+- Insert+- Update+- Delete+- Prepared Queries+- Batch Queries+- Automatic Records Conversion+- Collections++The driver gets the list of all nodes in the cluster and load balances amongst them. So you can connect to any one node in the cluster and it will+take care of the rest.++Initialize the driver by calling++@+ CQL.init host port+@++for example++@+ CQL.init "127.0.0.1" (PortNumber 9042)+@++Example:++@+data Emp = Emp {+ empID :: Int64,+ deptID :: Int32,+ alive :: Bool ,+ id :: UUID,+ name :: CQLString,+ salary :: CQLDouble,+ someList :: CQLList Int32,+ someSet :: CQLSet CQLDouble,+ someMap :: CQLMap CQLString CQLString+}+ deriving(Show, Eq)++deriveBuildRec ''Emp++main :: IO ()+main = do+ candle <- CQL.init "127.0.0.1" (PortNumber 9042)++ res <- flip runReaderT candle $ runExceptT $ do+ let q = create "keyspace demodb WITH REPLICATION = {'class' : 'SimpleStrategy','replication_factor': 1}"+ runCQL LOCAL_ONE q++ --create a table+ let tableQuery = "TABLE demodb.emp (empID bigint,deptID int,alive boolean,id uuid,name varchar,salary double,"+ ++ "someset set<double>,somelist list<int>,somemap map<text, text>,PRIMARY KEY (empID, deptID))"++ let q = create tableQuery+ runCQL LOCAL_ONE q++ --execute prepared queries+ p <- prepare "INSERT INTO demodb.emp (empID,deptID,alive,id,name,salary,somelist,someset,somemap) VALUES (?,?,?,?,?,?,?,?,?)"+ execCQL LOCAL_ONE p [+ put (104::Int64),+ put (15::Int32),+ put True,+ put $ fromJust $ fromString "38d0ceb1-9e3e-427c-bc36-0106398f672b",+ put $ CQLString "Hot Shot",+ put $ CQLDouble 100000.0,+ put ((CQLList [1,2,3,4,5,6]) :: CQLList Int32),+ put ((CQLSet $ fromList [CQLDouble 0.001, CQLDouble 1000.0]) :: CQLSet CQLDouble),+ put $ CQLMap $ DMS.fromList [(CQLString "some", CQLString "Things")]]++ -- execute prepared queries and get results+ p <- prepare "select empID, deptID, alive, id, name, salary, someset, somemap, somelist from demodb.emp where empid = ? and deptid = ?"+ res <- execCQL LOCAL_ONE p [+ put (104::Int64),+ put (15::Int32)]+ liftIO $ print $ catMaybes ((fmap fromRow res)::[Maybe Emp])+ liftIO $ print (fromCQL (Prelude.head res) (CQLString "salary")::Maybe Double)+ liftIO $ print (fromCQL (Prelude.head res) (CQLString "name")::Maybe CQLString)++ --select rows from table+ let q = select "demodb.emp" # where' "empID" (104::Int64) # and' "deptID" (15::Int32)+ rows <- runCQL LOCAL_ONE q+ liftIO $ print $ catMaybes ((fmap fromRow res)::[Maybe Emp])++ --batch queries+ p <- prepare "INSERT INTO demodb.emp (empID, deptID, alive, id, name, salary) VALUES (?, ?, ?, ?, ?, ?)"+ let q = batch (update "demodb.emp" # with "name" (CQLString "some name") # where' "empID" (104::Int64) # and' "deptID" (15::Int32)) <>+ batch (update "demodb.emp" # with "alive" False # where' "empID" (104::Int64) # and' "deptID" (15::Int32)) <>+ prepBatch p [+ put (101::Int64),+ put (13::Int32),+ put True,+ put $ fromJust $ fromString "48d0ceb1-9e3e-427c-bc36-0106398f672b",+ put $ CQLString "Hot1 Shot1",+ put $ CQLDouble 10000.0]+ runBatch q++ --drop a table+ let q = drop' "table demodb.emp"+ runCQL LOCAL_ONE q++ --drop a keyspace+ let q = drop' "keyspace demodb"+ runCQL LOCAL_ONE q++ print res++@++-}++module CQL (+ Driver.init,+ Consistency(..),+ -- ** Data Types+ Rows,+ Row,+ Bytes(..),+ CQLDouble(..),+ CQLString(..),+ CQLMap(..),+ CQLSet(..),+ CQLList(..),+ -- ** Auto derive conversion for record types+ deriveBuildRec,+ fromRow,+ -- ** DSL for creating queries+ (#),+ create,+ drop',+ select,+ limit,+ update,+ with,+ delete,+ where',+ and',+ -- ** Prepare and run queries+ runCQL,+ prepare,+ execCQL,+ -- ** Batching+ batch,+ prepBatch,+ runBatch) where++import Batch+import Codec+import Common+import Derive+import Driver+import Encoding+import Query
src/Common.hs view
@@ -74,7 +74,7 @@ deriving(Eq, Ord, Show) newtype LongStr = LongStr DBL.ByteString- deriving(Show)+ deriving(Show, Eq, Ord) newtype Bytes = Bytes DBL.ByteString deriving(Show, Eq, Ord)@@ -151,6 +151,7 @@ -- | Auto derivable class to get records from result rows. class BuildRec a where+ -- | Get the result from a row. fromRow :: Row -> Maybe a -- | All field types must implement this class.
src/Derive.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE QuasiQuotes #-}@@ -36,7 +37,11 @@ -- | Derives BuildRec instances for record types. deriveBuildRec a = do+#if __GLASGOW_HASKELL__ >= 800+ TyConI (DataD _ cName _ _ constructors _) <- reify a+#else TyConI (DataD _ cName _ constructors _) <- reify a+#endif case head constructors of (RecC conName args) -> do names <- genNames $ length args
src/Driver.hs view
@@ -4,16 +4,19 @@ {-# LANGUAGE ScopedTypeVariables #-} -module Driver (Driver.init) where+module Driver (Driver.init, Driver.allConnections) where +import Codec+import Common import Control.Applicative import Control.Concurrent import Control.Concurrent.MVar import Control.Concurrent.STM import Control.Concurrent.STM.TBQueue-import Control.Exception (bracket, catch)+import Control.Exception (bracket, catch, mask) import Control.Monad (forM_, forever, replicateM)+import Control.Monad.Except import Data.Binary import Data.Binary.Get import Data.Binary.IEEE754@@ -22,21 +25,21 @@ import Data.ByteString import qualified Data.ByteString.Char8 as C8 import qualified Data.ByteString.Lazy as DBL+import Data.Either import Data.Int import qualified Data.IntMap as IM import Data.List import qualified Data.Map.Strict as DMS--import Codec-import Common import Data.Maybe import Data.Monoid as DM+import Data.Set import Data.UUID import Debug.Trace import Encoding import GHC.Generics (Generic) import GHC.IO.Handle (Handle, hClose, hFlush) import Network+import System.IO.Unsafe startUp :: Handle -> IO ()@@ -50,18 +53,37 @@ return () +registerForEvents :: Handle -> IO ()+registerForEvents h = do+ let s = encode $ CQLList [CQLString "TOPOLOGY_CHANGE", CQLString "STATUS_CHANGE"]+ let register = DBL.toStrict $ DBL.pack [4, 0, 0, 1, 11] <> encode (fromIntegral (DBL.length s)::Int32) <> s+ hPut h register+ header <- hGet h 9+ he <- pure $ runGet (get :: Get Header) $ DBL.fromStrict header+ hGet h (fromIntegral $ len he)+ return ()+++{-# NOINLINE prepareQueries #-}+prepareQueries :: MVar (Set LongStr)+prepareQueries = unsafePerformIO $ do+ mvar <- newEmptyMVar+ putMVar mvar Data.Set.empty+ return mvar++ receiveThread :: Handle -> MVar [Int16] -> MVar(IM.IntMap (MVar (Either ShortStr Result))) -> IO () receiveThread h streams streamMap = do forkIO $ forever $ do header <- hGet h 9 he <- pure $ runGet (get :: Get Header) $ DBL.fromStrict header p <- hGet h (fromIntegral $ len he)- if opcode he == 0- then do+ case opcode he of+ 0 -> do let (erCode, erMsg) = runGet getErr (DBL.fromStrict p) mvar <- getResHolder he streams streamMap putMVar mvar (Left erMsg)- else do+ 8 -> do let resultType = runGet (get :: Get Int32) (DBL.fromStrict p) case resultType of@@ -82,6 +104,9 @@ 5 -> do mvar <- getResHolder he streams streamMap putMVar mvar (Right $ RRows [])+ -- 12 -> do+ -- print "something happened"+ -- print $ runGet (get :: Get ShortStr) (DBL.fromStrict p) return () @@ -97,35 +122,104 @@ return mvar +someDef :: Handle -> MVar [Int16] -> MVar (IM.IntMap (MVar (Either ShortStr Result))) -> (LongStr, Word8, MVar (Either ShortStr Result)) -> IO ()+someDef h streams streamMap (bs, opc, mvar) = do+ strs <- takeMVar streams+ case Data.List.uncons strs of+ Just (i, strsTail) -> do+ putMVar streams strsTail+ m <- takeMVar streamMap+ let m' = IM.insert (fromIntegral i :: Int) mvar m+ putMVar streamMap m'+ seq m' (return ())+ let bs' = Data.ByteString.pack [4, 0] <> DBL.toStrict (encode i <> DBL.pack [opc] <> encode bs)+ hPut h bs'++ Nothing -> do+ putMVar streams strs+ someDef h streams streamMap (bs, opc, mvar)++ sendThread :: Handle -> MVar [Int16] -> MVar(IM.IntMap (MVar (Either ShortStr Result))) -> TBQueue (LongStr, Word8, MVar (Either ShortStr Result)) -> IO () sendThread h streams streamMap driverQ = do forkIO $ forever $ do- strs <- takeMVar streams- case Data.List.uncons strs of- Just (i, strsTail) -> do- putMVar streams strsTail- (bs, opc, mvar) <- atomically $ readTBQueue driverQ- m <- takeMVar streamMap- let m' = IM.insert (fromIntegral i :: Int) mvar m- putMVar streamMap m'- seq m' (return ())- let bs' = Data.ByteString.pack [4, 0] <> DBL.toStrict (encode i <> DBL.pack [opc] <> encode bs)- hPut h bs'- Nothing -> do- putMVar streams strs- sendThread h streams streamMap driverQ+ (bs, opc, mvar) <- atomically $ readTBQueue driverQ+ when (opc == 9) $ do+ pq <- takeMVar prepareQueries+ putMVar prepareQueries (Data.Set.insert bs pq)+ cons <- readMVar allConnections+ mvars <- forM cons $ \(_, h', str, strMap) -> do+ mv <- newEmptyMVar+ someDef h' str strMap (bs, opc, mv)+ return mv+ forkIO $ do+ ls <- sequence $ fmap (\mva -> do {a <- takeMVar mva; return a}) mvars+ putMVar mvar $ Data.List.foldl' (\b a -> if isLeft a then a else b) (Data.List.head ls) (Data.List.tail ls)+ return ()+ when (opc /= 9) $ someDef h streams streamMap (bs, opc, mvar) return () --- | The first -init :: HostName -> PortID -> IO Candle++getPeers :: Handle -> IO (Either ShortStr [Row])+getPeers h = do+ let q' = "select peer from system.peers"+ let q = q' <> encode LOCAL_ONE <> encode (0x00 :: Int8)+ let l = fromIntegral (DBL.length q')::Int32+ let hd = LongStr $ encode l <> q+ let bs' = Data.ByteString.pack [4, 0] <> DBL.toStrict (encode (0::Int16) <> DBL.pack [7] <> encode hd)+ hPut h bs'+ header <- hGet h 9+ he <- pure $ runGet (get :: Get Header) $ DBL.fromStrict header+ p <- hGet h (fromIntegral $ len he)+ if opcode he == 0+ then do+ let (erCode, erMsg) = runGet getErr (DBL.fromStrict p)+ return $ Left erMsg+ else do+ let resultType = runGet (get :: Get Int32) (DBL.fromStrict p)+ case resultType of+ 2 -> do+ let rows = content $ runGet getRows (DBL.fromStrict $ C8.drop 4 p)+ return $ Right rows+ _ ->+ return $ Left $ ShortStr "Could not get list of peers. Please check if this cassandra version is supported."+++{-# NOINLINE allConnections #-}+allConnections :: MVar [(HostName, Handle, MVar [Int16], MVar(IM.IntMap (MVar (Either ShortStr Result))))]+allConnections = unsafePerformIO $ newMVar []+++-- | The first function you need to call. It initializes the driver and connects to the cluster.+-- You only need to specify one node from your cluster here.+init :: HostName -> PortID -> ExceptT ShortStr IO Candle init host port = do- streamNum <- newMVar 0- streams <- newMVar ([0..32767] :: [Int16])- streamMap <- newMVar (IM.empty :: (IM.IntMap (MVar (Either ShortStr Result))))- driverQ <- atomically $ newTBQueue 32768+ streamNum <- liftIO $ newMVar 0+ streams <- liftIO $ newMVar ([0..32767] :: [Int16])+ streamMap <- liftIO $ newMVar (IM.empty :: (IM.IntMap (MVar (Either ShortStr Result))))+ driverQ <- liftIO $ atomically $ newTBQueue 32768 - h <- connectTo host port- startUp h- receiveThread h streams streamMap- sendThread h streams streamMap driverQ- return $ Candle driverQ+ h <- liftIO $ connectTo host port+ liftIO $ startUp h+ -- liftIO $ registerForEvents h++ res <- liftIO $ getPeers h+ case res of+ Left err -> throwError err+ Right rows -> do+ let peers = (\(CQLString p) -> Data.List.concat <$> Data.List.intersperse "." $ fmap show (unpack p)) <$> catMaybes (fmap (\r -> fromCQL r (CQLString "peer")::Maybe CQLString) rows)+ oCons <- liftIO $ sequence $ fmap (\peer -> do+ streams <- newMVar ([0..32767] :: [Int16])+ streamMap <- newMVar (IM.empty :: (IM.IntMap (MVar (Either ShortStr Result))))+ h <- connectTo peer port+ startUp h+ -- registerForEvents h+ return (peer, h, streams, streamMap)+ ) peers+ let connections = (host, h, streams, streamMap) : oCons+ allCon <- liftIO $ takeMVar allConnections+ liftIO $ putMVar allConnections connections+ forM_ connections (\(_, h, streams, streamMap) -> do+ liftIO $ receiveThread h streams streamMap+ liftIO $ sendThread h streams streamMap driverQ)+ return $ Candle driverQ
src/Query.hs view
@@ -68,6 +68,7 @@ and' n v = Query (ShortStr (" and " <> DBL.fromStrict (C8.pack n) <> " = ? ")) [(DBL.toStrict . addLength . runPut . put) v] +-- | Prepare a query, returns a prepared query which can be fed to execCQL for execution. prepare :: ByteString -> ExceptT ShortStr (ReaderT Candle IO) Prepared prepare q = do (Candle driverQ) <- ask@@ -77,10 +78,11 @@ liftIO $ atomically $ writeTBQueue driverQ (LongStr hd, 9, mvar) res <- liftIO $ takeMVar mvar case res of- Left e -> throwError e- Right (RPrepared sb) -> return $ Prepared sb+ Left e -> throwError e+ Right (RPrepared sb) -> return $ Prepared sb +-- | Run a query directly. runCQL :: Consistency -> Q -> ExceptT ShortStr (ReaderT Candle IO) [Row] runCQL c (Query (ShortStr q) bs) = do (Candle driverQ) <- ask@@ -96,6 +98,7 @@ Right (RRows rows) -> return rows +-- | Execute a prepared query. execCQL :: Consistency -> Prepared -> [Put] -> ExceptT ShortStr (ReaderT Candle IO) [Row] execCQL c (Prepared pid) ls = do (Candle driverQ) <- ask@@ -109,6 +112,10 @@ Right (RRows rows) -> return rows +-- | Combine DSL actions+-- @+-- select "demodb.emp" # where' "empID" (104::Int64) # and' "deptID" (15::Int32)+-- @ (#) :: Q -> Q -> Q (#) (Query s1 bs1) (Query s2 bs2) = Query (s1 <> s2) (bs1 <> bs2)
test/Spec.hs view
@@ -60,80 +60,85 @@ main :: IO () main = do- ch <- CQL.init "127.0.0.1" (PortNumber 9042)+ conRes <- runExceptT $ CQL.init "127.0.0.1" (PortNumber 9042)+ case conRes of+ Right ch ->+ hspec $ before (threadDelay 1000000) (describe "driver should be able to" $ do+ it "create a keyspace" $ do+ let q = create "keyspace demodb WITH REPLICATION = {'class' : 'SimpleStrategy','replication_factor': 2}"+ res <- (runReaderT . runExceptT) (runCQL ALL q) ch+ res `shouldBe` Right [] - hspec $- describe "driver should be able to" $ do- it "create a keyspace" $ do- let q = create "keyspace demodb WITH REPLICATION = {'class' : 'SimpleStrategy','replication_factor': 1}"- res <- (runReaderT . runExceptT) (runCQL LOCAL_ONE q) ch- res `shouldBe` Right [] - it "create a table" $ do- let tableQuery = "TABLE demodb.emp (empID bigint,deptID int,alive boolean,id uuid,name varchar,salary double,"- ++ "someset set<double>,somelist list<int>,somemap map<text, text>,PRIMARY KEY (empID, deptID))"- let q = create tableQuery- res <- (runReaderT . runExceptT) (runCQL LOCAL_ONE q) ch- res `shouldBe` Right []+ it "create a table" $ do+ let tableQuery = "TABLE demodb.emp (empID bigint,deptID int,alive boolean,id uuid,name varchar,salary double,"+ ++ "someset set<double>,somelist list<int>,somemap map<text, text>,PRIMARY KEY (empID, deptID))"+ let q = create tableQuery+ res <- (runReaderT . runExceptT) (runCQL ALL q) ch+ res `shouldBe` Right [] - it "execute prepared queries" $ do- prep <- (runReaderT . runExceptT) (prepare "INSERT INTO demodb.emp (empID,deptID,alive,id,name,salary,somelist,someset,somemap) VALUES (?,?,?,?,?,?,?,?,?)") ch- case prep of- Left e -> print e- Right p -> do- res <- (runReaderT . runExceptT) (execCQL LOCAL_ONE p [- put (104::Int64),- put (15::Int32),- put True,- put $ fromJust $ fromString "38d0ceb1-9e3e-427c-bc36-0106398f672b",- put $ CQLString "Hot Shot",- put $ CQLDouble 100000.0,- put ((CQLList [1,2,3,4,5,6]) :: CQLList Int32),- put ((CQLSet $ fromList [CQLDouble 0.001, CQLDouble 1000.0]) :: CQLSet CQLDouble),- put $ CQLMap $ DMS.fromList [(CQLString "some", CQLString "Things")]]) ch- res `shouldBe` Right [] - it "execute prepared queries and get results" $ do- prep <- (runReaderT . runExceptT) (prepare "select empID, deptID, alive, id, name, salary, someset, somemap, somelist from demodb.emp where empid = ? and deptid = ?") ch- case prep of- Left e -> print e- Right p -> do- res <- (runReaderT . runExceptT) (execCQL LOCAL_ONE p [- put (104::Int64),- put (15::Int32)]) ch+ it "execute prepared queries" $ do+ prep <- (runReaderT . runExceptT) (prepare "INSERT INTO demodb.emp (empID,deptID,alive,id,name,salary,somelist,someset,somemap) VALUES (?,?,?,?,?,?,?,?,?)") ch+ case prep of+ Left e -> print e+ Right p -> do+ res <- (runReaderT . runExceptT) (execCQL QUORUM p [+ put (104::Int64),+ put (15::Int32),+ put True,+ put $ fromJust $ fromString "38d0ceb1-9e3e-427c-bc36-0106398f672b",+ put $ CQLString "Hot Shot",+ put $ CQLDouble 100000.0,+ put ((CQLList [1,2,3,4,5,6]) :: CQLList Int32),+ put ((CQLSet $ fromList [CQLDouble 0.001, CQLDouble 1000.0]) :: CQLSet CQLDouble),+ put $ CQLMap $ DMS.fromList [(CQLString "some", CQLString "Things")]]) ch+ res `shouldBe` Right []++ it "execute prepared queries and get results" $ do+ prep <- (runReaderT . runExceptT) (prepare "select empID, deptID, alive, id, name, salary, someset, somemap, somelist from demodb.emp where empid = ? and deptid = ?") ch+ case prep of+ Left e -> print e+ Right p -> do+ res <- (runReaderT . runExceptT) (execCQL QUORUM p [+ put (104::Int64),+ put (15::Int32)]) ch+ fmap fromRow <$> res `shouldBe` Right [Just (Emp {empID = 104, deptID = 15, alive = True, Main.id = fromJust $ fromString $ "38d0ceb1-9e3e-427c-bc36-0106398f672b", name = CQLString "Hot Shot", salary = CQLDouble 100000.0, someList = CQLList [1,2,3,4,5,6], someSet = CQLSet (fromList [CQLDouble 1.0e-3,CQLDouble 1000.0]), someMap = CQLMap $ DMS.fromList [(CQLString "some",CQLString "Things")]})]++ it "select rows from table" $ do+ let q = select "demodb.emp" # where' "empID" (104::Int64) # and' "deptID" (15::Int32)+ res <- (runReaderT . runExceptT) (runCQL QUORUM q) ch fmap fromRow <$> res `shouldBe` Right [Just (Emp {empID = 104, deptID = 15, alive = True, Main.id = fromJust $ fromString $ "38d0ceb1-9e3e-427c-bc36-0106398f672b", name = CQLString "Hot Shot", salary = CQLDouble 100000.0, someList = CQLList [1,2,3,4,5,6], someSet = CQLSet (fromList [CQLDouble 1.0e-3,CQLDouble 1000.0]), someMap = CQLMap $ DMS.fromList [(CQLString "some",CQLString "Things")]})] - it "select rows from table" $ do- let q = select "demodb.emp" # where' "empID" (104::Int64) # and' "deptID" (15::Int32)- res <- (runReaderT . runExceptT) (runCQL LOCAL_ONE q) ch- fmap fromRow <$> res `shouldBe` Right [Just (Emp {empID = 104, deptID = 15, alive = True, Main.id = fromJust $ fromString $ "38d0ceb1-9e3e-427c-bc36-0106398f672b", name = CQLString "Hot Shot", salary = CQLDouble 100000.0, someList = CQLList [1,2,3,4,5,6], someSet = CQLSet (fromList [CQLDouble 1.0e-3,CQLDouble 1000.0]), someMap = CQLMap $ DMS.fromList [(CQLString "some",CQLString "Things")]})]+ it "batch queries" $ do+ prep <- (runReaderT . runExceptT) (prepare "INSERT INTO demodb.emp (empID, deptID, alive, id, name, salary) VALUES (?, ?, ?, ?, ?, ?)") ch+ case prep of+ Left e -> print e+ Right p -> do+ let q = batch (update "demodb.emp" # with "name" (CQLString "some name") # where' "empID" (104::Int64) # and' "deptID" (15::Int32)) <>+ batch (update "demodb.emp" # with "alive" False # where' "empID" (104::Int64) # and' "deptID" (15::Int32)) <>+ prepBatch p [+ put (101::Int64),+ put (13::Int32),+ put True,+ put $ fromJust $ fromString "48d0ceb1-9e3e-427c-bc36-0106398f672b",+ put $ CQLString "Hot1 Shot1",+ put $ CQLDouble 10000.0]+ res <- (runReaderT . runExceptT) (runBatch q) ch+ res `shouldBe` Right []+ let q = select "demodb.emp" # where' "empID" (101::Int64) # and' "deptID" (13::Int32)+ res <- (runReaderT . runExceptT) (runCQL QUORUM q) ch+ fmap fromRow <$> res `shouldBe` Right [Just (Emp {empID = 101, deptID = 13, alive = True, Main.id = fromJust $ fromString $ "48d0ceb1-9e3e-427c-bc36-0106398f672b", name = CQLString "Hot1 Shot1", salary = CQLDouble 10000.0, someList = CQLList [], someSet = CQLSet Data.Set.empty, someMap = CQLMap DMS.empty})] - it "batch queries" $ do- prep <- (runReaderT . runExceptT) (prepare "INSERT INTO demodb.emp (empID, deptID, alive, id, name, salary) VALUES (?, ?, ?, ?, ?, ?)") ch- case prep of- Left e -> print e- Right p -> do- let q = batch (update "demodb.emp" # with "name" (CQLString "some name") # where' "empID" (104::Int64) # and' "deptID" (15::Int32)) <>- batch (update "demodb.emp" # with "alive" False # where' "empID" (104::Int64) # and' "deptID" (15::Int32)) <>- prepBatch p [- put (101::Int64),- put (13::Int32),- put True,- put $ fromJust $ fromString "48d0ceb1-9e3e-427c-bc36-0106398f672b",- put $ CQLString "Hot1 Shot1",- put $ CQLDouble 10000.0]- res <- (runReaderT . runExceptT) (runBatch q) ch+ it "drop a table" $ do+ let q = drop' "table demodb.emp"+ res <- (runReaderT . runExceptT) (runCQL ALL q) ch res `shouldBe` Right []- let q = select "demodb.emp" # where' "empID" (101::Int64) # and' "deptID" (13::Int32)- res <- (runReaderT . runExceptT) (runCQL LOCAL_ONE q) ch- fmap fromRow <$> res `shouldBe` Right [Just (Emp {empID = 101, deptID = 13, alive = True, Main.id = fromJust $ fromString $ "48d0ceb1-9e3e-427c-bc36-0106398f672b", name = CQLString "Hot1 Shot1", salary = CQLDouble 10000.0, someList = CQLList [], someSet = CQLSet Data.Set.empty, someMap = CQLMap DMS.empty})] - it "drop a table" $ do- let q = drop' "table demodb.emp"- res <- (runReaderT . runExceptT) (runCQL LOCAL_ONE q) ch- res `shouldBe` Right []+ it "drop a keyspace" $ do+ let q = drop' "keyspace demodb"+ res <- (runReaderT . runExceptT) (runCQL ALL q) ch+ res `shouldBe` Right []) - it "drop a keyspace" $ do- let q = drop' "keyspace demodb"- res <- (runReaderT . runExceptT) (runCQL LOCAL_ONE q) ch- res `shouldBe` Right []+ Left err ->+ print err