module Aws.DynamoDb.Commands.Query
( Query (..)
, Slice (..)
, query
, QueryResponse (..)
) where
import Control.Applicative
import Data.Aeson
import Data.Default
import Data.Maybe
import qualified Data.Text as T
import Data.Typeable
import qualified Data.Vector as V
import Aws.Core
import Aws.DynamoDb.Core
data Slice = Slice {
sliceHash :: Attribute
, sliceCond :: Maybe Condition
} deriving (Eq,Show,Read,Ord,Typeable)
data Query = Query {
qTableName :: T.Text
, qKeyConditions :: Slice
, qFilter :: Conditions
, qStartKey :: Maybe [Attribute]
, qLimit :: Maybe Int
, qForwardScan :: Bool
, qSelect :: QuerySelect
, qRetCons :: ReturnConsumption
, qIndex :: Maybe T.Text
, qConsistent :: Bool
} deriving (Eq,Show,Read,Ord,Typeable)
instance ToJSON Query where
toJSON Query{..} = object $
catMaybes
[ (("ExclusiveStartKey" .= ) . attributesJson) <$> qStartKey
, ("Limit" .= ) <$> qLimit
, ("IndexName" .= ) <$> qIndex
] ++
conditionsJson "QueryFilter" qFilter ++
querySelectJson qSelect ++
[ "ScanIndexForward" .= qForwardScan
, "TableName".= qTableName
, "KeyConditions" .= sliceJson qKeyConditions
, "ReturnConsumedCapacity" .= qRetCons
, "ConsistentRead" .= qConsistent
]
query
:: T.Text
-> Slice
-> Query
query tn sl = Query tn sl def Nothing Nothing True def def Nothing False
data QueryResponse = QueryResponse {
qrItems :: V.Vector Item
, qrLastKey :: Maybe [Attribute]
, qrCount :: Int
, qrScanned :: Int
, qrConsumed :: Maybe ConsumedCapacity
} deriving (Eq,Show,Read,Ord)
instance FromJSON QueryResponse where
parseJSON (Object v) = QueryResponse
<$> v .:? "Items" .!= V.empty
<*> ((do o <- v .: "LastEvaluatedKey"
Just <$> parseAttributeJson o)
<|> pure Nothing)
<*> v .: "Count"
<*> v .: "ScannedCount"
<*> v .:? "ConsumedCapacity"
parseJSON _ = fail "QueryResponse must be an object."
instance Transaction Query QueryResponse
instance SignQuery Query where
type ServiceConfiguration Query = DdbConfiguration
signQuery gi = ddbSignQuery "Query" gi
instance ResponseConsumer r QueryResponse where
type ResponseMetadata QueryResponse = DdbResponse
responseConsumer _ ref resp = ddbResponseConsumer ref resp
instance AsMemoryResponse QueryResponse where
type MemoryResponse QueryResponse = QueryResponse
loadToMemory = return
instance ListResponse QueryResponse Item where
listResponse = V.toList . qrItems
instance IteratedTransaction Query QueryResponse where
nextIteratedRequest request response = case qrLastKey response of
Nothing -> Nothing
key -> Just request { qStartKey = key }
sliceJson :: Slice -> Value
sliceJson Slice{..} = object (map conditionJson cs)
where
cs = maybe [] return sliceCond ++ [hashCond]
hashCond = Condition (attrName sliceHash) (DEq (attrVal sliceHash))