Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

JSON module now uses ByteString columns (to allow packing)

  • Loading branch information...
commit ec1c368c8ca7205b20a6a32c226b475dc8fa3bb4 1 parent a377ba8
Ozgun Ataman ozataman authored
4 cassy.cabal
View
@@ -1,5 +1,5 @@
Name: cassy
-Version: 0.3.1
+Version: 0.3.2
Synopsis: A high level driver for the Cassandra datastore
License: BSD3
License-file: LICENSE
@@ -52,11 +52,13 @@ Library
Database.Cassandra.JSON
Database.Cassandra.Pool
Database.Cassandra.Types
+ Database.Cassandra.Pack
-- Packages needed in order to build this package.
Build-depends:
base >= 4 && < 5
, bytestring
+ , binary
, containers
, network
, time
8 src/Database/Cassandra/Basic.hs
View
@@ -52,13 +52,16 @@ module Database.Cassandra.Basic
, Row
, ConsistencyLevel(..)
+ -- * Helpers
+ , CKey (..)
+ , packLong
) where
-------------------------------------------------------------------------------
+import Control.Applicative
import Control.Exception
import Control.Monad
-import Control.Applicative
import Control.Monad.IO.Class
import Control.Monad.Trans.Reader
import Data.ByteString.Lazy (ByteString)
@@ -66,10 +69,11 @@ import Data.Map (Map)
import qualified Data.Map as M
import Data.Maybe (mapMaybe)
import qualified Database.Cassandra.Thrift.Cassandra_Client as C
-import qualified Database.Cassandra.Thrift.Cassandra_Types as T
import Database.Cassandra.Thrift.Cassandra_Types (ConsistencyLevel (..))
+import qualified Database.Cassandra.Thrift.Cassandra_Types as T
import Prelude hiding (catch)
-------------------------------------------------------------------------------
+import Database.Cassandra.Pack
import Database.Cassandra.Pool
import Database.Cassandra.Types
-------------------------------------------------------------------------------
120 src/Database/Cassandra/JSON.hs
View
@@ -10,9 +10,12 @@
{-|
A higher level module for working with Cassandra.
- Row and Column keys can be any string-like type implementing the
- CKey typeclass. You can add your own types by defining new instances
+ All row and column keys are standardized to be of strict types.
+ Row keys are Text, while Column keys are ByteString. This might change
+ in the future and we may revert to entirely ByteString keys.
+
+
Serialization and de-serialization of Column values are taken care of
automatically using the ToJSON and FromJSON typeclasses.
@@ -23,10 +26,10 @@ module Database.Cassandra.JSON
-- * Connection
CPool
- , Server(..)
+ , Server (..)
, defServer
, defServers
- , KeySpace(..)
+ , KeySpace (..)
, createCassandraPool
-- * MonadCassandra Typeclass
@@ -44,17 +47,23 @@ module Database.Cassandra.JSON
, delete
-- * Necessary Types
- , CKey(..)
- , ModifyOperation(..)
- , ColumnFamily(..)
- , ConsistencyLevel(..)
- , CassandraException(..)
- , Selector(..)
- , KeySelector(..)
+ , RowKey
+ , ColumnName
+ , ModifyOperation (..)
+ , ColumnFamily (..)
+ , ConsistencyLevel (..)
+ , CassandraException (..)
+ , Selector (..)
+ , KeySelector (..)
+ , KeyRangeType (..)
+
+ -- * Helpers
+ , CKey (..)
+ , packLong
) where
-
+-------------------------------------------------------------------------------
import Control.Exception
import Control.Monad
import Data.Aeson as A
@@ -67,55 +76,26 @@ import Data.Int (Int32, Int64)
import Data.Map (Map)
import qualified Data.Map as M
import qualified Data.Text as T
+import Data.Text (Text)
import qualified Data.Text.Encoding as T
import qualified Data.Text.Lazy as LT
import qualified Data.Text.Lazy.Encoding as LT
import Network
import Prelude hiding (catch)
-
+-------------------------------------------------------------------------------
import Database.Cassandra.Basic hiding (get, getCol, delete, KeySelector (..),
getMulti)
import qualified Database.Cassandra.Basic as CB
import Database.Cassandra.Pool
-import Database.Cassandra.Types hiding (KeySelector (..))
-
-
--------------------------------------------------------------------------------
----- CKey Typeclass
+import Database.Cassandra.Types hiding (KeySelector (..), ColumnName)
+import Database.Cassandra.Pack
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- | A typeclass to enable using any string-like type for row and column keys
-class CKey a where
- toBS :: a -> ByteString
- fromBS :: ByteString -> a
-
-instance CKey String where
- toBS = LB.pack
- fromBS = LB.unpack
-
-instance CKey LT.Text where
- toBS = LT.encodeUtf8
- fromBS = LT.decodeUtf8
-
-instance CKey T.Text where
- toBS = toBS . LT.fromChunks . return
- fromBS = T.concat . LT.toChunks . fromBS
-
-instance CKey B.ByteString where
- toBS = LB.fromChunks . return
- fromBS = B.concat . LB.toChunks . fromBS
-
-instance CKey ByteString where
- toBS = id
- fromBS = id
-
-
-------------------------------------------------------------------------------
-- | Convert regular column to a key-value pair
-col2val :: (CKey colKey, FromJSON a) => Column -> (colKey, a)
+col2val :: (FromJSON a) => Column -> (ColumnName, a)
col2val (Column nm val _ _) = (fromBS nm, maybe err id $ unMarshallJSON' val)
where err = error "Value can't be parsed from JSON."
col2val _ = error "col2val is not implemented for SuperColumns"
@@ -131,6 +111,10 @@ data ModifyOperation a =
deriving (Eq,Show,Ord,Read)
+-------------------------------------------------------------------------------
+type RowKey = Text
+
+
------------------------------------------------------------------------------
-- | A modify function that will fetch a specific column, apply modification
-- function on it and save results back to Cassandra.
@@ -144,10 +128,10 @@ data ModifyOperation a =
-- This method may throw a 'CassandraException' for all exceptions other than
-- 'NotFoundException'.
modify
- :: (MonadCassandra m, CKey rowKey, CKey colKey, ToJSON a, FromJSON a)
+ :: (MonadCassandra m, ToJSON a, FromJSON a)
=> ColumnFamily
- -> rowKey
- -> colKey
+ -> RowKey
+ -> ColumnName
-> ConsistencyLevel
-- ^ Read quorum
-> ConsistencyLevel
@@ -185,10 +169,10 @@ modify cf k cn rcl wcl f =
-- This method may throw a 'CassandraException' for all exceptions other than
-- 'NotFoundException'.
modify_
- :: (MonadCassandra m, CKey rowKey, CKey colKey, ToJSON a, FromJSON a)
+ :: (MonadCassandra m, ToJSON a, FromJSON a)
=> ColumnFamily
- -> rowKey
- -> colKey
+ -> RowKey
+ -> ColumnName
-> ConsistencyLevel
-- ^ Read quorum
-> ConsistencyLevel
@@ -210,10 +194,10 @@ modify_ cf k cn rcl wcl f =
-------------------------------------------------------------------------------
-- Simple insertion function making use of typeclasses
insertCol
- :: (MonadCassandra m, CKey rowKey, CKey colKey, ToJSON a)
+ :: (MonadCassandra m, ToJSON a)
=> ColumnFamily
- -> rowKey
- -> colKey
+ -> RowKey
+ -> ColumnName
-> ConsistencyLevel
-> a -- ^ Content
-> m ()
@@ -228,12 +212,12 @@ insertCol cf k cn cl a =
-- ColumnFamily and contents of returned columns are cast into the
-- target type.
get
- :: (MonadCassandra m, CKey rowKey, CKey colKey, FromJSON a)
+ :: (MonadCassandra m, FromJSON a)
=> ColumnFamily
- -> rowKey
+ -> RowKey
-> Selector
-> ConsistencyLevel
- -> m [(colKey, a)]
+ -> m [(ColumnName, a)]
get cf k s cl = do
res <- CB.get cf (toBS k) s cl
return $ map col2val res
@@ -241,8 +225,8 @@ get cf k s cl = do
-------------------------------------------------------------------------------
data KeySelector
- = forall k. CKey k => Keys [k]
- | forall k. CKey k => KeyRange KeyRangeType k k Int32
+ = Keys [RowKey]
+ | KeyRange KeyRangeType RowKey RowKey Int32
-------------------------------------------------------------------------------
@@ -255,12 +239,12 @@ ksToBasicKS (KeyRange ty fr to i) = CB.KeyRange ty (toBS fr) (toBS to) i
-- since we are auto-serializing from JSON, all the columns must be of
-- the same data type.
getMulti
- :: (MonadCassandra m, Ord rowKey, CKey rowKey, CKey colKey, FromJSON a)
+ :: (MonadCassandra m, FromJSON a)
=> ColumnFamily
-> KeySelector
-> Selector
-> ConsistencyLevel
- -> m (Map rowKey [(colKey, a)])
+ -> m (Map RowKey [(ColumnName, a)])
getMulti cf ks s cl = do
res <- CB.getMulti cf (ksToBasicKS ks) s cl
return . M.fromList . map conv . M.toList $ res
@@ -271,10 +255,10 @@ getMulti cf ks s cl = do
-------------------------------------------------------------------------------
-- | Get a single column from a single row
getCol
- :: (MonadCassandra m, CKey rowKey, CKey colKey, FromJSON a)
+ :: (MonadCassandra m, FromJSON a)
=> ColumnFamily
- -> rowKey
- -> colKey
+ -> RowKey
+ -> ColumnName
-> ConsistencyLevel
-> m (Maybe a)
getCol cf rk ck cl = do
@@ -282,7 +266,7 @@ getCol cf rk ck cl = do
case res of
Nothing -> return Nothing
Just res' -> do
- let (_ :: ByteString, x) = col2val res'
+ let (_, x) = col2val res'
return $ Just x
@@ -291,10 +275,10 @@ getCol cf rk ck cl = do
-- it throws an exception rather than returning an explicit Either
-- value.
delete
- :: (MonadCassandra m, CKey rowKey)
+ :: (MonadCassandra m)
=>ColumnFamily
-- ^ In 'ColumnFamily'
- -> rowKey
+ -> RowKey
-- ^ Key to be deleted
-> Selector
-- ^ Columns to be deleted
47 src/Database/Cassandra/Types.hs
View
@@ -5,17 +5,23 @@
module Database.Cassandra.Types where
-import Control.Monad
+-------------------------------------------------------------------------------
import Control.Exception
-import Data.Generics
-import Data.ByteString.Lazy (ByteString)
+import Control.Monad
import qualified Data.ByteString.Char8 as B
+import Data.ByteString.Lazy (ByteString)
import qualified Data.ByteString.Lazy.Char8 as LB
+import Data.Generics
import Data.Int (Int32, Int64)
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy as LT
+import qualified Data.Text.Lazy.Encoding as LT
import Data.Time
import Data.Time.Clock.POSIX
-
import qualified Database.Cassandra.Thrift.Cassandra_Types as C
+-------------------------------------------------------------------------------
-- | A 'Key' range selector to use with 'getMulti'.
@@ -177,3 +183,36 @@ getTime = do
t <- getPOSIXTime
return . fromIntegral . floor $ t * 1000000
+
+
+ --------------------
+ -- CKey Typeclass --
+ --------------------
+
+------------------------------------------------------------------------------
+-- | A typeclass to enable using any string-like type for row and column keys
+class CKey a where
+ toBS :: a -> ByteString
+ fromBS :: ByteString -> a
+
+instance CKey String where
+ toBS = LB.pack
+ fromBS = LB.unpack
+
+instance CKey LT.Text where
+ toBS = LT.encodeUtf8
+ fromBS = LT.decodeUtf8
+
+instance CKey T.Text where
+ toBS = toBS . LT.fromChunks . return
+ fromBS = T.concat . LT.toChunks . fromBS
+
+instance CKey B.ByteString where
+ toBS = LB.fromChunks . return
+ fromBS = B.concat . LB.toChunks . fromBS
+
+instance CKey ByteString where
+ toBS = id
+ fromBS = id
+
+
Please sign in to comment.
Something went wrong with that request. Please try again.