Permalink
Browse files

Add simplistic CPS-style pagination support for wide rows (by column)

  • Loading branch information...
1 parent 896d9f1 commit 0fc39f20590db80f5c5778d9b407adcfc404d6a2 @ozataman ozataman committed Feb 21, 2013
Showing with 70 additions and 0 deletions.
  1. +33 −0 src/Database/Cassandra/Marshall.hs
  2. +37 −0 src/Database/Cassandra/Types.hs
@@ -1,5 +1,6 @@
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternGuards #-}
@@ -80,6 +81,14 @@ module Database.Cassandra.Marshall
, KeySelector (..)
, KeyRangeType (..)
+
+ -- * Pagination
+ , PageResult (..)
+ , pIsDry
+ , pIsDone
+ , pHasMore
+ , paginate
+
-- * Helpers
, CKey (..)
, fromColKey'
@@ -393,3 +402,27 @@ col2val Marshall{..} c = f $ unpackCol c
err s = error $ "Cassandra Marshall: Value can't be decoded: " ++ s
col2val _ _ = error "col2val is not implemented for SuperColumns"
+
+
+-------------------------------------------------------------------------------
+-- | Paginate over columns in a given key, repeatedly applying the
+-- given 'Selector'. The 'Selector' must be a 'Range' selector, or
+-- else this funtion will raise an exception.
+paginate
+ :: (MonadCassandra m, CasType k)
+ => Marshall a
+ -> ColumnFamily
+ -> RowKey
+ -> Selector
+ -> ConsistencyLevel
+ -> m (PageResult m (k, a))
+paginate m cf k rng@(Range from to ord per) cl = do
+ cs <- reverse `liftM` get m cf k rng cl
+ case cs of
+ [] -> return $ PDone []
+ [a] -> return $ PDone [a]
+ _ ->
+ let cont = paginate m cf k (Range (Just cn) to ord per) cl
+ (cn, _) = head cs
+ in return $ PMore (reverse (drop 1 cs)) cont
+paginate _ _ _ _ _ = error "Must call paginate with a Range selector"
@@ -251,6 +251,43 @@ getTime = do
return . fromIntegral . floor $ t * 1000000
+ ----------------
+ -- Pagination --
+ ----------------
+
+
+-------------------------------------------------------------------------------
+-- | Describes the result of a single pagination action
+data PageResult m a
+ = PDone { pCache :: [a] }
+ -- ^ Done, this is all I have.
+ | PMore { pCache :: [a], pMore :: (m (PageResult m a)) }
+ -- ^ Here's a batch and there is more when you call the action.
+
+
+
+
+-------------------------------------------------------------------------------
+pIsDry x = pIsDone x && null (pCache x)
+
+-------------------------------------------------------------------------------
+pIsDone PDone{} = True
+pIsDone _ = False
+
+
+-------------------------------------------------------------------------------
+pHasMore PMore{} = True
+pHasMore _ = False
+
+
+-------------------------------------------------------------------------------
+instance Monad m => Functor (PageResult m) where
+ fmap f (PDone as) = PDone (fmap f as)
+ fmap f (PMore as m) = PMore (fmap f as) m'
+ where
+ m' = liftM (fmap f) m
+
+
--------------------
-- CKey Typeclass --

0 comments on commit 0fc39f2

Please sign in to comment.