diff --git a/CHANGELOG.md b/CHANGELOG.md index 01568f1c90..bfea327720 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - #2153, Fix --dump-schema running with a wrong PG version. - @wolfgangwalther - #2042, Keep working when EMFILE(Too many open files) is reached. - @steve-chavez - #2147, Ignore `Content-Type` headers for `GET` requests when calling RPCs. Previously, `GET` without parameters, but with `Content-Type: text/plain` or `Content-Type: application/octet-stream` would fail with `404 Not Found`, even if a function without arguments was available. + - #2155, Ignore `max-rows` on POST, PATCH, PUT and DELETE - @steve-chavez ### Changed @@ -48,6 +49,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). + Previously, those RPCs would return "null" as a body with Content-Type: application/json. - #2156, `limit/offset` now limits the affected rows on UPDATE/DELETE - @steve-chavez + Previously, `limit/offset` only limited the returned rows but not the actual updated rows + - #2155, `max-rows` is no longer applied on POST/PATCH/PUT/DELETE returned rows - @steve-chavez + + This was misleading because the affected rows were not really affected by `max-rows`, only the returned rows were limited ## [9.0.0] - 2021-11-25 diff --git a/src/PostgREST/Request/DbRequestBuilder.hs b/src/PostgREST/Request/DbRequestBuilder.hs index 428069a2fa..44de9e9993 100644 --- a/src/PostgREST/Request/DbRequestBuilder.hs +++ b/src/PostgREST/Request/DbRequestBuilder.hs @@ -63,7 +63,7 @@ import Protolude hiding (from) readRequest :: Schema -> TableName -> Maybe Integer -> [Relationship] -> ApiRequest -> Either Error ReadRequest readRequest schema rootTableName maxRows allRels apiRequest = mapLeft ApiRequestError $ - treeRestrictRange maxRows =<< + treeRestrictRange maxRows (iAction apiRequest) =<< augmentRequestWithJoin schema rootRels =<< addLogicTrees apiRequest =<< addRanges apiRequest =<< @@ -115,8 +115,9 @@ initReadRequest rootQi = fldForest:rForest -- | Enforces the `max-rows` config on the result -treeRestrictRange :: Maybe Integer -> ReadRequest -> Either ApiRequestError ReadRequest -treeRestrictRange maxRows request = pure $ nodeRestrictRange maxRows <$> request +treeRestrictRange :: Maybe Integer -> Action -> ReadRequest -> Either ApiRequestError ReadRequest +treeRestrictRange _ (ActionMutate _) request = Right request +treeRestrictRange maxRows _ request = pure $ nodeRestrictRange maxRows <$> request where nodeRestrictRange :: Maybe Integer -> ReadNode -> ReadNode nodeRestrictRange m (q@Select {range_=r}, i) = (q{range_=restrictRange m r }, i) diff --git a/test/spec/Feature/Query/QueryLimitedSpec.hs b/test/spec/Feature/Query/QueryLimitedSpec.hs index eb89abadea..addca7907c 100644 --- a/test/spec/Feature/Query/QueryLimitedSpec.hs +++ b/test/spec/Feature/Query/QueryLimitedSpec.hs @@ -77,3 +77,40 @@ spec = , matchHeaders = [ matchContentTypeJson , "Content-Range" <:> "0-1/3" ] } + + context "max-rows=2 on mutations" $ do + it "doesn't affect insertions" $ + request methodPost "/projects?select=id,name" + [("Prefer", "return=representation")] + [json| [ + { "id": 6, "name": "BeOS" }, + { "id": 7, "name": "PopOS" }, + { "id": 8, "name": "HaikuOS" } ]|] + `shouldRespondWith` + [json| [ + { "id": 6, "name": "BeOS" }, + { "id": 7, "name": "PopOS" }, + { "id": 8, "name": "HaikuOS" } ]|] + { matchStatus = 201 } + + it "doesn't affect updates" $ + request methodPatch "/employees?select=first_name,last_name,occupation" + [("Prefer", "return=representation")] + [json| [{"occupation": "Barista"}] |] + `shouldRespondWith` + [json|[ + { "first_name": "Frances M.", "last_name": "Roe", "occupation": "Barista" }, + { "first_name": "Daniel B.", "last_name": "Lyon", "occupation": "Barista" }, + { "first_name": "Edwin S.", "last_name": "Smith", "occupation": "Barista" } ]|] + { matchStatus = 200 } + + it "doesn't affect deletions" $ + request methodDelete "/employees?select=first_name,last_name" + [("Prefer", "return=representation")] + mempty + `shouldRespondWith` + [json| [ + { "first_name": "Frances M.", "last_name": "Roe" }, + { "first_name": "Daniel B.", "last_name": "Lyon" }, + { "first_name": "Edwin S.", "last_name": "Smith" } ]|] + { matchStatus = 200 }