packages feed

tablestorage 0.1.0.1 → 0.1.0.2

raw patch · 9 files changed

+155/−53 lines, 9 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Network.TableStorage.API: createTableIfNecessary :: Account -> String -> IO (Either String ())
+ Network.TableStorage.API: defaultAccount :: AccountKey -> String -> String -> Account
+ Network.TableStorage.Query: edmBinary :: String -> Entity -> Maybe String
+ Network.TableStorage.Query: edmBoolean :: String -> Entity -> Maybe Bool
+ Network.TableStorage.Query: edmDateTime :: String -> Entity -> Maybe UTCTime
+ Network.TableStorage.Query: edmDouble :: String -> Entity -> Maybe Double
+ Network.TableStorage.Query: edmGuid :: String -> Entity -> Maybe String
+ Network.TableStorage.Query: edmInt32 :: String -> Entity -> Maybe Int
+ Network.TableStorage.Query: edmInt64 :: String -> Entity -> Maybe Int
+ Network.TableStorage.Query: edmString :: String -> Entity -> Maybe String
+ Network.TableStorage.Types: accountResourcePrefix :: Account -> String
+ Network.TableStorage.Types: accountScheme :: Account -> String
- Network.TableStorage.Types: Account :: String -> Int -> AccountKey -> String -> Account
+ Network.TableStorage.Types: Account :: String -> String -> Int -> AccountKey -> String -> String -> Account

Files

src/Network/TableStorage.hs view
@@ -13,3 +13,4 @@ import Network.TableStorage.Types as TableStorage import Network.TableStorage.API as TableStorage import Network.TableStorage.Development as TableStorage+import Network.TableStorage.Query as TableStorage
src/Network/TableStorage/API.hs view
@@ -2,9 +2,10 @@ -- This module provides functions wrapping the Azure REST API web methods.  module Network.TableStorage.API (-  queryTables, createTable, deleteTable,+  queryTables, createTable, createTableIfNecessary, deleteTable,   insertEntity, updateEntity, mergeEntity, deleteEntity, -  queryEntity, queryEntities, defaultEntityQuery+  queryEntity, queryEntities, defaultEntityQuery,+  defaultAccount ) where  import Network.HTTP@@ -38,7 +39,7 @@ -- queryTables :: Account -> IO (Either String [String]) queryTables acc = do-  let resource = printf "/%s/Tables" $ accountName acc+  let resource = "/Tables"   response <- authenticatedRequest acc GET [] resource resource ""   return $ response >>= parseQueryTablesResponse @@ -53,17 +54,32 @@ -- createTable :: Account -> String -> IO (Either String ()) createTable acc tableName = do -  let resource = printf "/%s/Tables" (accountName acc)+  let resource = "/Tables"   requestXml <- createTableXml tableName   response <- authenticatedRequest acc POST [] resource resource $ showTopElement requestXml   return $ response >>= parseEmptyResponse (2, 0, 1)  -- |+-- Creates a new table with the specified name if it does not already exist, or returns an erro message+-- +createTableIfNecessary :: Account -> String -> IO (Either String ())+createTableIfNecessary acc tableName = do +  tables <- queryTables acc+  case tables of+    Left err -> return $ Left err+    Right tables' -> +      if any (== tableName) tables'+      then+        return $ Right ()+      else +        createTable acc tableName++-- | -- Deletes the table with the specified name or returns an error message -- deleteTable :: Account -> String -> IO (Either String ()) deleteTable acc tableName = do -  let resource = printf "/%s/Tables('%s')" (accountName acc) tableName+  let resource = printf "/Tables('%s')" tableName   response <- authenticatedRequest acc DELETE [] resource resource ""   return $ response >>= parseEmptyResponse (2, 0, 4) @@ -84,7 +100,7 @@ -- insertEntity :: Account -> String -> Entity -> IO (Either String ()) insertEntity acc tableName entity = do -  let resource = printf "/%s/%s" (accountName acc) tableName+  let resource = printf "/%s" tableName   requestXml <- createInsertEntityXml entity   response <- authenticatedRequest acc POST [] resource resource $ showTopElement requestXml   return $ response >>= parseEmptyResponse (2, 0, 1)  @@ -95,7 +111,7 @@ -- updateOrMergeEntity :: RequestMethod -> Account -> String -> Entity -> IO (Either String ()) updateOrMergeEntity method acc tableName entity = do -  let resource = entityKeyResource acc tableName $ entityKey entity+  let resource = entityKeyResource tableName $ entityKey entity   let additionalHeaders = [ Header (HdrCustom "If-Match") "*" ]   requestXml <- createInsertEntityXml entity   response <- authenticatedRequest acc method additionalHeaders resource resource $ showTopElement requestXml@@ -118,7 +134,7 @@ -- deleteEntity :: Account -> String -> EntityKey -> IO (Either String ()) deleteEntity acc tableName key = do -  let resource = entityKeyResource acc tableName key+  let resource = entityKeyResource tableName key   let additionalHeaders = [ Header (HdrCustom "If-Match") "*" ]   response <- authenticatedRequest acc DELETE additionalHeaders resource resource ""   return $ response >>= parseEmptyResponse (2, 0, 4)@@ -157,7 +173,7 @@ -- queryEntity :: Account -> String -> EntityKey -> IO (Either String Entity) queryEntity acc tableName key = do -  let resource = entityKeyResource acc tableName key+  let resource = entityKeyResource tableName key   response <- authenticatedRequest acc GET [] resource resource ""   return $ response >>= parseQueryEntityResponse @@ -176,7 +192,7 @@ -- queryEntities :: Account -> String -> EntityQuery -> IO (Either String [Entity]) queryEntities acc tableName query = do -  let canonicalizedResource = printf "/%s/%s()" (accountName acc) tableName+  let canonicalizedResource = printf "/%s()" tableName   let queryString = buildQueryString query   let resource = printf "%s?%s" canonicalizedResource queryString   response <- authenticatedRequest acc GET [] resource canonicalizedResource ""@@ -188,3 +204,13 @@ defaultEntityQuery :: EntityQuery defaultEntityQuery = EntityQuery { eqPageSize = Nothing,                                    eqFilter = Nothing }+                                   +-- | +-- Constructs an Account with the default values for Port and Resource Prefix+defaultAccount :: AccountKey -> String -> String -> Account+defaultAccount key name hostname = Account { accountScheme              = "http",+                                             accountHost                = hostname,+                                             accountPort                = 80,+                                             accountKey                 = key,+                                             accountName                = name,+                                             accountResourcePrefix      = "" }
src/Network/TableStorage/Auth.hs view
@@ -66,14 +66,14 @@ -- qualifyResource :: String -> Account -> URI qualifyResource res acc =-  URI { uriScheme = "http",+  URI { uriScheme = accountScheme acc,         uriAuthority =             Just URIAuth { uriRegName = accountHost acc,                           uriPort = ':' : show (accountPort acc),                          uriUserInfo = "" },         uriQuery = "",         uriFragment = "",-        uriPath = res }+        uriPath = (accountResourcePrefix acc) ++ res }  -- | -- Creates and executes an authenticated request including the Authorization header.@@ -90,7 +90,7 @@                              sharedKeyAuthContentMD5 = "",                              sharedKeyAuthContentType = "application/atom+xml",                              sharedKeyAuthDate = time,-                             sharedKeyAuthCanonicalizedResource = '/' : accountName acc ++ canonicalizedResource }+                             sharedKeyAuthCanonicalizedResource = printf "/%s%s%s" (accountName acc) (accountResourcePrefix acc) canonicalizedResource }   let basicHeaders = [ Header HdrAuthorization (authHeader acc auth),                        Header HdrContentType "application/atom+xml",                        Header HdrContentLength (show $ length body),
src/Network/TableStorage/Development.hs view
@@ -2,29 +2,17 @@ -- This module contains constants for working with the storage emulator.   -- -module Network.TableStorage.Development (-  developmentAccount-) where+module Network.TableStorage.Development where  import Network.TableStorage.Types -developmentAccountName :: String-developmentAccountName = "devstoreaccount1"--developmentKey :: AccountKey-developmentKey = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="--developmentHost :: String-developmentHost = "127.0.0.1"--developmentPort :: Int-developmentPort = 10002- -- | -- An account for the storage emulator -- developmentAccount :: Account-developmentAccount = Account { accountName = developmentAccountName,-                               accountKey = developmentKey, -                               accountHost = developmentHost,-                               accountPort = developmentPort }+developmentAccount = Account { accountScheme            = "http",+                               accountHost              = "127.0.0.1" ,+                               accountName              = "devstoreaccount1",+                               accountPort              = 10002,+                               accountResourcePrefix    = "/devstoreaccount1",+                               accountKey               = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="}
+ src/Network/TableStorage/Query.hs view
@@ -0,0 +1,79 @@+-- |
+-- This module contains functions which help when unmarshalling query responses
+
+module Network.TableStorage.Query where
+
+import Data.Time
+import Network.TableStorage.Types
+
+-- |
+-- Find the value in a binary-valued column or return Nothing if no such column exists
+edmBinary :: String -> Entity -> Maybe String
+edmBinary key en = do
+  col <- lookup key $ entityColumns en
+  case col of
+    EdmBinary s -> s
+    _ -> Nothing
+    
+-- |
+-- Find the value in a string-valued column or return Nothing if no such column exists
+edmString :: String -> Entity -> Maybe String
+edmString key en = do
+  col <- lookup key $ entityColumns en
+  case col of
+    EdmString s -> s
+    _ -> Nothing
+
+-- |
+-- Find the value in a boolean-valued column or return Nothing if no such column exists
+edmBoolean :: String -> Entity -> Maybe Bool
+edmBoolean key en = do
+  col <- lookup key $ entityColumns en
+  case col of
+    EdmBoolean s -> s
+    _ -> Nothing
+
+-- |
+-- Find the value in a date-valued column or return Nothing if no such column exists
+edmDateTime :: String -> Entity -> Maybe UTCTime
+edmDateTime key en = do
+  col <- lookup key $ entityColumns en
+  case col of
+    EdmDateTime s -> s
+    _ -> Nothing
+
+-- |
+-- Find the value in a double-valued column or return Nothing if no such column exists
+edmDouble :: String -> Entity -> Maybe Double
+edmDouble key en = do
+  col <- lookup key $ entityColumns en
+  case col of
+    EdmDouble s -> s
+    _ -> Nothing
+
+-- |
+-- Find the value in a Guid-valued column or return Nothing if no such column exists
+edmGuid :: String -> Entity -> Maybe String
+edmGuid key en = do
+  col <- lookup key $ entityColumns en
+  case col of
+    EdmGuid s -> s
+    _ -> Nothing
+
+-- |
+-- Find the value in an integer-valued column or return Nothing if no such column exists
+edmInt32 :: String -> Entity -> Maybe Int
+edmInt32 key en = do
+  col <- lookup key $ entityColumns en
+  case col of
+    EdmInt32 s -> s
+    _ -> Nothing
+
+-- |
+-- Find the value in an integer-valued column or return Nothing if no such column exists
+edmInt64 :: String -> Entity -> Maybe Int
+edmInt64 key en = do
+  col <- lookup key $ entityColumns en
+  case col of
+    EdmInt64 s -> s
+    _ -> Nothing
src/Network/TableStorage/Request.hs view
@@ -35,9 +35,8 @@ -- Constructs relative URIs which refer to the entity with the specified table name -- and entity key.  ---entityKeyResource :: Account -> String -> EntityKey -> String-entityKeyResource acc tableName key = printf "/%s/%s(PartitionKey='%s',RowKey='%s')" -  (accountName acc) +entityKeyResource :: String -> EntityKey -> String+entityKeyResource tableName key = printf "%s(PartitionKey='%s',RowKey='%s')"    tableName    (ekPartitionKey key)    (ekRowKey key)
src/Network/TableStorage/Response.hs view
@@ -24,6 +24,12 @@   return $ strContent message  -- |+-- Summarize an error appearing in a response body or return "Unknown error" if the response cannot be parsed+--+errorToString :: Response_String -> String+errorToString res = fromMaybe "Unknown error" (parseXMLDoc (rspBody res) >>= parseError)++-- | -- Verifies a response code, parsing an error message if necessary. -- parseEmptyResponse :: ResponseCode -> Response_String -> Either String ()@@ -32,7 +38,7 @@   then     Right ()   else-    Left $ fromMaybe "Unknown error" (parseXMLDoc (rspBody res) >>= parseError)+    Left $ errorToString res  -- | -- Parse an XML response, or an error response as appropriate.
src/Network/TableStorage/Types.hs view
@@ -25,10 +25,12 @@ -- | -- Account information: host, port, secret key and account name  ---data Account = Account { accountHost :: String,-                         accountPort :: Int,-                         accountKey  :: AccountKey,-                         accountName :: String } deriving Show               +data Account = Account { accountScheme         :: String,+                         accountHost           :: String,+                         accountPort           :: Int,+                         accountKey            :: AccountKey,+                         accountName           :: String,+                         accountResourcePrefix :: String } deriving Show                 -- | -- The unencrypted content of the Shared Key authorization header 
tablestorage.cabal view
@@ -1,5 +1,5 @@ name:           tablestorage-version:        0.1.0.1+version:        0.1.0.2 cabal-version:  >= 1.2 build-type:     Simple author:         Phil Freeman <paf31-at-cantab.net>@@ -34,16 +34,17 @@                    xml,
                    old-locale
   ghc-options:     -Wall-  exposed-modules: -                   Network.TableStorage,-                   Network.TableStorage.API,-                   Network.TableStorage.Auth,-                   Network.TableStorage.Development,-                   Network.TableStorage.Types-  other-modules:   -                   Network.TableStorage.Atom,-                   Network.TableStorage.Format,-                   Network.TableStorage.Request,-                   Network.TableStorage.Response,-                   Network.TableStorage.XML+  exposed-modules: 
+                   Network.TableStorage,
+                   Network.TableStorage.API,
+                   Network.TableStorage.Auth,
+                   Network.TableStorage.Development,
+                   Network.TableStorage.Query,
+                   Network.TableStorage.Types
+  other-modules:   
+                   Network.TableStorage.Atom,
+                   Network.TableStorage.Format,
+                   Network.TableStorage.Request,
+                   Network.TableStorage.Response,
+                   Network.TableStorage.XML