diff --git a/README.md b/README.md index e81d93c00..dda08b35e 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ your own projects. ### Usage -Download the binary ([OS X](http://bin.begriffs.com/dbapi/osx/postgrest-0.2.4.10.tar.xz) / [Ubuntu](http://bin.begriffs.com/dbapi/heroku/postgrest-0.2.4.10.tar.xz)) and invoke like so: +Download the binary ([OS X](http://bin.begriffs.com/dbapi/osx/postgrest-0.2.5.0.tar.xz) / [Ubuntu](http://bin.begriffs.com/dbapi/heroku/postgrest-0.2.5.0.tar.xz)) and invoke like so: ```bash postgrest --db-host localhost --db-port 5432 \ diff --git a/postgrest.cabal b/postgrest.cabal index b32f1b3f3..fd0ea9f0f 100644 --- a/postgrest.cabal +++ b/postgrest.cabal @@ -1,5 +1,5 @@ name: postgrest -version: 0.2.4.10 +version: 0.2.5.0 synopsis: The database is your api license: MIT license-file: LICENSE diff --git a/src/App.hs b/src/App.hs index 32ac72bd6..19c3e4122 100644 --- a/src/App.hs +++ b/src/App.hs @@ -153,6 +153,18 @@ app reqBody req = $ update qt (map cs $ keys obj) (elems obj) return $ responseLBS status204 [ jsonH ] "" + ([table], "DELETE") -> do + let qt = QualifiedTable schema (cs table) + let del = coerce $ countT + . returningStarT + . whereT qq + $ deleteFrom qt + row <- H.single del + let (Identity deletedCount) = fromMaybe (Identity 0 :: Identity Int) row + return $ if deletedCount == 0 + then responseLBS status404 [] "" + else responseLBS status204 [("Content-Range", "*/"<> cs (show deletedCount))] "" + (_, _) -> return $ responseLBS status404 [] "" diff --git a/src/PgQuery.hs b/src/PgQuery.hs index 06a8957e7..2aa95071f 100644 --- a/src/PgQuery.hs +++ b/src/PgQuery.hs @@ -74,6 +74,12 @@ iffNotT (aq, ap, apre) (bq, bp, bpre) = , All $ getAll apre && getAll bpre ) +countT :: StatementT +countT (sql, params, pre) = + ("WITH qqq AS (" <> sql <> ") SELECT count(1) FROM qqq" + , params + , pre) + countRows :: QualifiedTable -> DynamicSQL countRows t = ("select count(1) from " <> fromQt t, [], mempty) @@ -93,6 +99,14 @@ selectStar :: QualifiedTable -> DynamicSQL selectStar t = ("select * from " <> fromQt t, [], mempty) +returningStarT :: StatementT +returningStarT (sql, params, pre) = + (sql <> " RETURNING *", params, pre) + +deleteFrom :: QualifiedTable -> DynamicSQL +deleteFrom t = + ("delete from " <> fromQt t, [], mempty) + insertInto :: QualifiedTable -> [Text] -> [JSON.Value] -> DynamicSQL insertInto t [] _ = ("insert into " <> fromQt t <> " default values returning *", [], mempty) diff --git a/test/Feature/DeleteSpec.hs b/test/Feature/DeleteSpec.hs new file mode 100644 index 000000000..adf946e50 --- /dev/null +++ b/test/Feature/DeleteSpec.hs @@ -0,0 +1,37 @@ +module Feature.DeleteSpec where + +import Test.Hspec +import Test.Hspec.Wai +import SpecHelper + +import Network.HTTP.Types + +spec :: Spec +spec = beforeAll (clearTable "items" >> createItems 15) . afterAll_ (clearTable "items") + . around withApp $ + describe "Deleting" $ do + context "existing record" $ do + it "succeeds with 204 and deletion count" $ + request methodDelete "/items?id=eq.1" [] "" + `shouldRespondWith` ResponseMatcher { + matchBody = Nothing + , matchStatus = 204 + , matchHeaders = ["Content-Range" <:> "*/1"] + } + + it "actually clears items ouf the db" $ do + _ <- request methodDelete "/items?id=lt.15" [] "" + get "/items" + `shouldRespondWith` ResponseMatcher { + matchBody = Just "[{\"id\":15}]" + , matchStatus = 200 + , matchHeaders = ["Content-Range" <:> "0-0/1"] + } + + context "known route, unknown record" $ + it "fails with 404" $ + request methodDelete "/items?id=eq.101" [] "" `shouldRespondWith` 404 + + context "totally unknown route" $ + it "fails with 404" $ + request methodDelete "/foozle?id=eq.101" [] "" `shouldRespondWith` 404