packages feed

dynamodb-simple 0.4.0.0 → 0.5.0.0

raw patch · 8 files changed

+62/−16 lines, 8 filesdep +uuid-typesdep ~amazonka-dynamodbdep ~bytestringPVP ok

version bump matches the API change (PVP)

Dependencies added: uuid-types

Dependency ranges changed: amazonka-dynamodb, bytestring

API changes (from Hackage documentation)

+ Database.DynamoDB: querySourceByKey :: forall a parent hash rest v1 m r. (DynamoIndex a parent NoRange, Code a ~ '[hash : rest], DynamoScalar v1 hash, MonadAWS m, DynamoTable parent r) => Proxy a -> hash -> Source m a
+ Database.DynamoDB.Types: instance Database.DynamoDB.Types.DynamoEncodable Data.UUID.Types.Internal.UUID
+ Database.DynamoDB.Types: instance Database.DynamoDB.Types.DynamoScalar 'Network.AWS.DynamoDB.Types.Sum.S Data.UUID.Types.Internal.UUID
- Database.DynamoDB: qConsistentRead :: forall a_a15F6 hash_a15F7 range_a15F8. Lens' (QueryOpts a_a15F6 hash_a15F7 range_a15F8) Consistency
+ Database.DynamoDB: qConsistentRead :: forall a_a18KQ hash_a18KR range_a18KS. Lens' (QueryOpts a_a18KQ hash_a18KR range_a18KS) Consistency
- Database.DynamoDB: qDirection :: forall a_a15F6 hash_a15F7 range_a15F8. Lens' (QueryOpts a_a15F6 hash_a15F7 range_a15F8) Direction
+ Database.DynamoDB: qDirection :: forall a_a18KQ hash_a18KR range_a18KS. Lens' (QueryOpts a_a18KQ hash_a18KR range_a18KS) Direction
- Database.DynamoDB: qFilterCondition :: forall a_a15F6 hash_a15F7 range_a15F8 a_a15HJ. Lens (QueryOpts a_a15F6 hash_a15F7 range_a15F8) (QueryOpts a_a15HJ hash_a15F7 range_a15F8) (Maybe (FilterCondition a_a15F6)) (Maybe (FilterCondition a_a15HJ))
+ Database.DynamoDB: qFilterCondition :: forall a_a18KQ hash_a18KR range_a18KS a_a18Nt. Lens (QueryOpts a_a18KQ hash_a18KR range_a18KS) (QueryOpts a_a18Nt hash_a18KR range_a18KS) (Maybe (FilterCondition a_a18KQ)) (Maybe (FilterCondition a_a18Nt))
- Database.DynamoDB: qHashKey :: forall a_a15F6 hash_a15F7 range_a15F8. Lens' (QueryOpts a_a15F6 hash_a15F7 range_a15F8) hash_a15F7
+ Database.DynamoDB: qHashKey :: forall a_a18KQ hash_a18KR range_a18KS. Lens' (QueryOpts a_a18KQ hash_a18KR range_a18KS) hash_a18KR
- Database.DynamoDB: qLimit :: forall a_a15F6 hash_a15F7 range_a15F8. Lens' (QueryOpts a_a15F6 hash_a15F7 range_a15F8) (Maybe Natural)
+ Database.DynamoDB: qLimit :: forall a_a18KQ hash_a18KR range_a18KS. Lens' (QueryOpts a_a18KQ hash_a18KR range_a18KS) (Maybe Natural)
- Database.DynamoDB: qRangeCondition :: forall a_a15F6 hash_a15F7 range_a15F8. Lens' (QueryOpts a_a15F6 hash_a15F7 range_a15F8) (Maybe (RangeOper range_a15F8))
+ Database.DynamoDB: qRangeCondition :: forall a_a18KQ hash_a18KR range_a18KS. Lens' (QueryOpts a_a18KQ hash_a18KR range_a18KS) (Maybe (RangeOper range_a18KS))
- Database.DynamoDB: qStartKey :: forall a_a15F6 hash_a15F7 range_a15F8. Lens' (QueryOpts a_a15F6 hash_a15F7 range_a15F8) (Maybe (hash_a15F7, range_a15F8))
+ Database.DynamoDB: qStartKey :: forall a_a18KQ hash_a18KR range_a18KS. Lens' (QueryOpts a_a18KQ hash_a18KR range_a18KS) (Maybe (hash_a18KR, range_a18KS))
- Database.DynamoDB: sConsistentRead :: forall a_a15Jd r_a15Je. Lens' (ScanOpts a_a15Jd r_a15Je) Consistency
+ Database.DynamoDB: sConsistentRead :: forall a_a18OZ r_a18P0. Lens' (ScanOpts a_a18OZ r_a18P0) Consistency
- Database.DynamoDB: sFilterCondition :: forall a_a15Jd r_a15Je. Lens' (ScanOpts a_a15Jd r_a15Je) (Maybe (FilterCondition a_a15Jd))
+ Database.DynamoDB: sFilterCondition :: forall a_a18OZ r_a18P0. Lens' (ScanOpts a_a18OZ r_a18P0) (Maybe (FilterCondition a_a18OZ))
- Database.DynamoDB: sLimit :: forall a_a15Jd r_a15Je. Lens' (ScanOpts a_a15Jd r_a15Je) (Maybe Natural)
+ Database.DynamoDB: sLimit :: forall a_a18OZ r_a18P0. Lens' (ScanOpts a_a18OZ r_a18P0) (Maybe Natural)
- Database.DynamoDB: sParallel :: forall a_a15Jd r_a15Je. Lens' (ScanOpts a_a15Jd r_a15Je) (Maybe (Natural, Natural))
+ Database.DynamoDB: sParallel :: forall a_a18OZ r_a18P0. Lens' (ScanOpts a_a18OZ r_a18P0) (Maybe (Natural, Natural))
- Database.DynamoDB: sStartKey :: forall a_a15Jd r_a15Je r_a16oc. Lens (ScanOpts a_a15Jd r_a15Je) (ScanOpts a_a15Jd r_a16oc) (Maybe (PrimaryKey a_a15Jd r_a15Je)) (Maybe (PrimaryKey a_a15Jd r_a16oc))
+ Database.DynamoDB: sStartKey :: forall a_a18OZ r_a18P0 r_a19yR. Lens (ScanOpts a_a18OZ r_a18P0) (ScanOpts a_a18OZ r_a19yR) (Maybe (PrimaryKey a_a18OZ r_a18P0)) (Maybe (PrimaryKey a_a18OZ r_a19yR))
- Database.DynamoDB.Types: scalarDecode :: (DynamoScalar v a, Show a, Read a) => ScalarValue S -> Maybe a
+ Database.DynamoDB.Types: scalarDecode :: (DynamoScalar v a, Show a, Read a, v ~ S) => ScalarValue v -> Maybe a
- Database.DynamoDB.Types: scalarEncode :: (DynamoScalar v a, Show a, Read a) => a -> ScalarValue S
+ Database.DynamoDB.Types: scalarEncode :: (DynamoScalar v a, Show a, Read a, v ~ S) => a -> ScalarValue v

Files

changelog.md view
@@ -1,8 +1,14 @@+# 0.4.0.1++- Fixed default signatures to compile with GHC 8.2+ # 0.4.0.0+ - Slightly changed TH API to allow table prefixing - Better consistency settings detection for queryOverIndex  # 0.3.0.0+ - API changes regarding position of `Proxy` - Added index->table conversion functions - Added conduits for left/inner join
dynamodb-simple.cabal view
@@ -1,5 +1,5 @@ name:                dynamodb-simple-version:             0.4.0.0+version:             0.5.0.0 synopsis:            Typesafe library for working with DynamoDB database description:         Framework for accessing DynamoDB database. The majority of AWS API                      is available to the user in a convenient, simple and typesafe manner.@@ -27,13 +27,13 @@                        Database.DynamoDB.Internal, Database.DynamoDB.BatchRequest,                        Database.DynamoDB.QueryRequest, Database.DynamoDB.THLens,                        Database.DynamoDB.THContains, Database.DynamoDB.THConvert-  build-depends:       base >=4.8 && <5, amazonka-dynamodb, generics-sop,+  build-depends:       base >=4.8 && <5, amazonka-dynamodb >= 1.4.5, generics-sop,                        unordered-containers, text, lens, double-conversion,-                       semigroups, bytestring, containers, monad-supply,+                       semigroups, bytestring >= 0.10.8.0, containers, monad-supply,                        template-haskell, transformers, exceptions,                        amazonka, monad-loops, conduit, hashable,                        amazonka-core, aeson, vector, scientific,-                       tagged+                       tagged, uuid-types                        -- hspec, safe-exceptions   hs-source-dirs:      src   default-language:    Haskell2010
src/Database/DynamoDB.hs view
@@ -49,6 +49,7 @@   , queryCond   , querySource   , querySourceChunks+  , querySourceByKey   , queryOverIndex     -- * Scan options   , ScanOpts
src/Database/DynamoDB/Class.hs view
@@ -27,7 +27,7 @@     DynamoCollection(..)   , DynamoTable(..)   , DynamoIndex(..)-  , dScan+  , defaultScan   , RangeType(..)   , TableType(..)   , gsDecode@@ -161,16 +161,13 @@   -- | Return table name and index name   qsTableName :: Proxy a -> T.Text   qsIndexName :: Proxy a -> Maybe T.Text-  dScan :: Proxy a -> D.Scan instance (DynamoCollection a r 'IsTable, DynamoTable a r) => TableScan a r 'IsTable where   qsTableName = tableName   qsIndexName _ = Nothing-  dScan = defaultScan instance (DynamoCollection a r 'IsIndex,           DynamoIndex a parent r, DynamoTable parent r1, HasPrimaryKey a r 'IsIndex) => TableScan a r 'IsIndex where   qsTableName _ = tableName (Proxy :: Proxy parent)   qsIndexName = Just . indexName-  dScan = defaultScan  -- | Type family that returns a primary key of a table/index depending on the 'RangeType' parameter. type PrimaryKey a r = PrimaryKey' (Code a) r
src/Database/DynamoDB/Migration.hs view
@@ -243,6 +243,7 @@       Left _ -> do           logmsg Info ("Creating table: " <> prettyTableInfo tabledef)           void $ send tabledef -- table doesn't exist, create a new one+          waitUntilTableActive tblname True       Right rs         | Just descr <- rs ^. D.drsTable -> do             logmsg Info ("Table " <> tblname <> " alread exists, checking schema.")
src/Database/DynamoDB/QueryRequest.hs view
@@ -21,6 +21,7 @@   , querySource   , querySourceChunks   , queryOverIndex+  , querySourceByKey   -- * Scan   , scan   , scanCond@@ -40,8 +41,7 @@ ) where  -import           Control.Arrow                  (first)-import           Control.Arrow                  (second)+import           Control.Arrow                  (first, second) import           Control.Lens                   (Lens', sequenceOf, view, (%~),                                                  (.~), (^.), _2) import           Control.Lens.TH                (makeLenses)@@ -68,6 +68,7 @@ import qualified Network.AWS.DynamoDB.Types     as D import           Network.AWS.Pager              (AWSPager (..)) import           Numeric.Natural                (Natural)+import qualified Data.HashMap.Strict as HMap  import           Database.DynamoDB.BatchRequest (getItemBatch) import           Database.DynamoDB.Class@@ -152,13 +153,32 @@   => Proxy a -> QueryOpts a hash range -> Source m [a] querySourceChunks _ q = paginate (FixedQuery (queryCmd q)) =$= CL.mapM (\res -> mapM rsDecoder (res ^. D.qrsItems)) - -- | Generic query function. You can query table or indexes that have -- a range key defined. The filter condition cannot access the hash and range keys. querySource :: forall a t m hash range. (CanQuery a t hash range, MonadAWS m)   => Proxy a -> QueryOpts a hash range -> Source m a querySource p q = querySourceChunks p q =$= CL.concat ++querySourceChunksByKey :: forall a parent hash rest v1 m r.+  (DynamoIndex a parent 'NoRange, Code a ~ '[ hash ': rest ], DynamoScalar v1 hash, MonadAWS m,+   DynamoTable parent r)+  => Proxy a -> hash -> Source m [a]+querySourceChunksByKey p key = paginate (FixedQuery sQuery) =$= CL.mapM (\res -> mapM rsDecoder (res ^. D.qrsItems))+  where+    sQuery = D.query (tableName (Proxy :: Proxy parent))+                                   & D.qKeyConditionExpression .~ Just "#K = :key"+                                   & D.qExpressionAttributeNames .~ HMap.singleton "#K" (head (allFieldNames p))+                                   & D.qExpressionAttributeValues .~ HMap.singleton ":key" (dScalarEncode key)+                                   & D.qIndexName .~ (Just $ indexName p)++-- | Conduit to query global indexes with no range key; in case anyone needed it+querySourceByKey :: forall a parent hash rest v1 m r.+  (DynamoIndex a parent 'NoRange, Code a ~ '[ hash ': rest ], DynamoScalar v1 hash, MonadAWS m,+   DynamoTable parent r)+  => Proxy a -> hash -> Source m a+querySourceByKey p q = querySourceChunksByKey p q =$= CL.concat+ -- | Query an index, fetch primary key from the result and immediately read -- full items from the main table. --@@ -310,7 +330,7 @@ -- | Generate a "D.Query" object. scanCmd :: forall a r t. TableScan a r t => ScanOpts a r -> D.Scan scanCmd q =-    dScan (Proxy :: Proxy a)+    defaultScan (Proxy :: Proxy a)         & D.sConsistentRead . consistencyL .~ (q ^. sConsistentRead)         & D.sLimit .~ (q ^. sLimit)         & addStartKey (q ^. sStartKey)
src/Database/DynamoDB/Types.hs view
@@ -46,6 +46,8 @@ import qualified Data.HashMap.Strict         as HMap import           Data.Maybe                  (mapMaybe) import           Data.Proxy+import           Data.UUID.Types             (UUID)+import qualified Data.UUID.Types             as UUID import           Data.Scientific             (Scientific, floatingOrInteger,                                               fromFloatDigits, toBoundedInteger,                                               toRealFloat)@@ -114,11 +116,11 @@ class ScalarAuto v => DynamoScalar (v :: D.ScalarAttributeType) a | a -> v where   -- | Scalars must have total encoding function   scalarEncode :: a -> ScalarValue v-  default scalarEncode :: (Show a, Read a) => a -> ScalarValue 'D.S+  default scalarEncode :: (Show a, Read a, v ~ 'D.S) => a -> ScalarValue v   scalarEncode = ScS . T.pack . show    scalarDecode :: ScalarValue v -> Maybe a-  default scalarDecode :: (Show a, Read a) => ScalarValue 'D.S -> Maybe a+  default scalarDecode :: (Show a, Read a, v ~ 'D.S) => ScalarValue v -> Maybe a   scalarDecode (ScS txt) = readMaybe (T.unpack txt)  instance DynamoScalar 'D.N Integer where@@ -240,6 +242,14 @@   dDecode Nothing = Just ""   dIsMissing "" = True   dIsMissing _ = False+++instance DynamoEncodable UUID where+  dEncode uuid = dEncode (UUID.toText uuid)+  dDecode attr = attr >>= dDecode . Just >>= UUID.fromText+instance DynamoScalar 'D.S UUID where+  scalarEncode = ScS . UUID.toText+  scalarDecode (ScS txt) = UUID.fromText txt  -- | 'Maybe' ('Maybe' a) will not work well; it will 'join' the value in the database. instance DynamoEncodable a => DynamoEncodable (Maybe a) where
test/BaseSpec.hs view
@@ -42,8 +42,13 @@   , iInt      :: Int   , iMText    :: Maybe T.Text } deriving (Show, Eq, Ord)-mkTableDefs "migrateTest" (tableConfig "" (''Test, WithRange) [] []) +data TestKeyOnly = TestKeyOnly {+    d_iText :: T.Text+  , d_iHashKey  :: T.Text+}+mkTableDefs "migrateTest" (tableConfig "" (''Test, WithRange) [(''TestKeyOnly, NoRange)] [])+ data TestSecond = TestSecond {     tHashKey :: T.Text   , tInt :: Int@@ -158,6 +163,13 @@         putItemBatch newItems         (items :: [Test]) <- queryCond tTest "hashkey" Nothing (iInt' >. 50) Backward (-1)         liftIO $ items `shouldBe` []+    withDb "querySourceByKey works/compiles correctly" $ do+      let template i = Test "hashkey" i "text" False 3.14 i Nothing+          newItems = map template [1..55]+      putItemBatch newItems+      res <- runConduit $ querySourceByKey iTestKeyOnly "text" =$= CL.consume+      liftIO $ length res `shouldBe` 55+     withDb "updateItemByKey works" $ do         let testitem1 = Test "1" 2 "text" False 3.14 2 (Just "something")         putItem testitem1@@ -227,7 +239,6 @@                               =$= leftJoin Strongly tTestSecond iMText                               =$= CL.concat =$= CL.consume         liftIO $ res2 `shouldBe` [(testitem1, Nothing), (testitem2, Just testsecond)]-  main :: IO () main = hspec spec