packages feed

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 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