module Database.Cassandra.Types where
import Control.Exception
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
data KeySelector =
Keys [Key]
| KeyRange KeyRangeType Key Key Int32
deriving (Show)
data KeyRangeType = InclusiveRange | WrapAround
deriving (Show)
mkKeyRange (KeyRange ty st end cnt) = case ty of
InclusiveRange -> C.KeyRange (Just st) (Just end) Nothing Nothing (Just cnt)
WrapAround -> C.KeyRange Nothing Nothing (Just $ LB.unpack st) (Just $ LB.unpack end) (Just cnt)
data Selector =
All
| ColNames [ColumnName]
| SupNames ColumnName [ColumnName]
| Range (Maybe ColumnName) (Maybe ColumnName) Order Int32
deriving (Show)
mkPredicate :: Selector -> C.SlicePredicate
mkPredicate s =
let
allRange = C.SliceRange (Just "") (Just "") (Just False) (Just 100)
in case s of
All -> C.SlicePredicate Nothing (Just allRange)
ColNames ks -> C.SlicePredicate (Just ks) Nothing
Range st end ord cnt ->
let
st' = st `mplus` Just ""
end' = end `mplus` Just ""
in C.SlicePredicate Nothing
(Just (C.SliceRange st' end' (Just $ renderOrd ord) (Just cnt)))
data Order = Regular | Reversed
deriving (Show)
renderOrd Regular = False
renderOrd Reversed = True
type ColumnFamily = String
type Key = ByteString
type ColumnName = ByteString
type Value = ByteString
data Column =
SuperColumn ColumnName [Column]
| Column {
colKey :: ColumnName
, colVal :: Value
, colTS :: Maybe Int64
, colTTL :: Maybe Int32
}
deriving (Eq,Show,Read,Ord)
type Row = [Column]
col :: ByteString -> ByteString -> Column
col k v = Column k v Nothing Nothing
mkThriftCol :: Column -> IO C.Column
mkThriftCol Column{..} = do
now <- getTime
return $ C.Column (Just colKey) (Just colVal) (Just now) colTTL
mkThriftCol _ = error "mkThriftCol can only process regular columns."
castColumn :: C.ColumnOrSuperColumn -> Either CassandraException Column
castColumn x | Just c <- C.f_ColumnOrSuperColumn_column x = castCol c
| Just c <- C.f_ColumnOrSuperColumn_super_column x = castSuperCol c
castColumn _ =
Left $ ConversionException "castColumn: Unsupported/unexpected ColumnOrSuperColumn type"
castCol :: C.Column -> Either CassandraException Column
castCol c
| Just nm <- C.f_Column_name c
, Just val <- C.f_Column_value c
, Just ts <- C.f_Column_timestamp c
, ttl <- C.f_Column_ttl c
= Right $ Column nm val (Just ts) ttl
castCol _ = Left $ ConversionException "Can't parse Column"
castSuperCol :: C.SuperColumn -> Either CassandraException Column
castSuperCol c
| Just nm <- C.f_SuperColumn_name c
, Just cols <- C.f_SuperColumn_columns c
, Right cols' <- mapM castCol cols
= Right $ SuperColumn nm cols'
castSuperCol _ = Left $ ConversionException "Can't parse SuperColumn"
data CassandraException =
NotFoundException
| InvalidRequestException String
| UnavailableException
| TimedOutException
| AuthenticationException String
| AuthorizationException String
| SchemaDisagreementException
| ConversionException String
| OperationNotSupported String
deriving (Eq,Show,Read,Ord,Data,Typeable)
instance Exception CassandraException
getTime :: IO Int64
getTime = do
t <- getPOSIXTime
return . fromIntegral . floor $ t * 1000000
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