diff --git a/src/PostgREST/QueryBuilder.hs b/src/PostgREST/QueryBuilder.hs index e679c6587..c58bf6f09 100644 --- a/src/PostgREST/QueryBuilder.hs +++ b/src/PostgREST/QueryBuilder.hs @@ -268,7 +268,7 @@ requestToQuery schema isParent (DbRead (Node (Select colSelects tbl tblAlias imp --getQueryParts is not total but requestToQuery is called only after addJoinConditions which ensures the only --posible relations are Child Parent Many getQueryParts _ _ = witness -requestToQuery schema _ (DbMutate (Insert mainTbl p@(PayloadJSON _ _ pKeys) onConflct putConditions returnings)) = +requestToQuery schema _ (DbMutate (Insert mainTbl (PayloadJSON _ _ pKeys) onConflct putConditions returnings)) = unwords [ "WITH payload AS (SELECT $1::json AS json_data),", "vals AS (", @@ -276,7 +276,7 @@ requestToQuery schema _ (DbMutate (Insert mainTbl p@(PayloadJSON _ _ pKeys) onCo "SELECT json_data AS val FROM payload WHERE json_typeof(json_data) = 'array'", "UNION ALL", "SELECT json_build_array(json_data) AS val FROM payload WHERE json_typeof(json_data) = 'object')"], - "INSERT INTO ", fromQi qi, if payloadIsEmpty then " " else "(" <> cols <> ")", + "INSERT INTO ", fromQi qi, if S.null pKeys then " " else "(" <> cols <> ")", unwords [ "SELECT " <> cols <> " FROM", "json_populate_recordset", "(null::", fromQi qi, ", (select val from vals)) _", @@ -293,10 +293,9 @@ requestToQuery schema _ (DbMutate (Insert mainTbl p@(PayloadJSON _ _ pKeys) onCo where qi = QualifiedIdentifier schema mainTbl cols = intercalate ", " $ pgFmtIdent <$> S.toList pKeys - payloadIsEmpty = pjIsEmpty p -requestToQuery schema _ (DbMutate (Update mainTbl p@(PayloadJSON _ _ keys) logicForest returnings)) = - if pjIsEmpty p - then "WITH " <> ignoredBody <> "SELECT ''" +requestToQuery schema _ (DbMutate (Update mainTbl (PayloadJSON _ _ keys) logicForest returnings)) = + if S.null keys + then "WITH " <> ignoredBody <> "SELECT null WHERE false" -- if there are no columns we cannot do UPDATE table SET {empty}, it'd be invalid syntax else unwords [ "WITH payload AS (SELECT $1::json AS json_data),", diff --git a/test/Feature/InsertSpec.hs b/test/Feature/InsertSpec.hs index 24e77e0b0..c1430cc5c 100644 --- a/test/Feature/InsertSpec.hs +++ b/test/Feature/InsertSpec.hs @@ -222,12 +222,23 @@ spec = do , matchHeaders = ["Location" <:> location] } - context "empty object" $ - it "successfully populates table with all-default columns" $ + context "empty objects" $ do + it "successfully inserts a row with all-default columns" $ do post "/items" "{}" `shouldRespondWith` "" { matchStatus = 201 , matchHeaders = [] } + post "/items" "[{}]" `shouldRespondWith` "" + { matchStatus = 201 + , matchHeaders = [] + } + + it "successfully inserts two rows with all-default columns" $ + post "/items" "[{}, {}]" `shouldRespondWith` "" + { matchStatus = 201 + , matchHeaders = [] + } + context "table with limited privileges" $ do it "succeeds if correct select is applied" $ request methodPost "/limited_article_stars?select=article_id,user_id" [("Prefer", "return=representation")] @@ -427,20 +438,20 @@ spec = do matchHeaders = ["Content-Range" <:> "*/*"] } - get "/items" `shouldRespondWith` - [json|[{"id":3},{"id":4},{"id":5},{"id":6},{"id":7},{"id":8},{"id":9},{"id":10},{"id":11},{"id":12},{"id":13},{"id":14},{"id":15},{id:16},{"id":2},{"id":1}]|] - { matchHeaders = [matchContentTypeJson] } + request methodPatch "/items" [] [json| [{}] |] + `shouldRespondWith` "" + { + matchStatus = 204, + matchHeaders = ["Content-Range" <:> "*/*"] + } - it "makes no updates and and returns 200, when patching with an empty json object and return=rep" $ do + it "makes no updates and and returns 200, when patching with an empty json object and return=rep" $ request methodPatch "/items" [("Prefer", "return=representation")] [json| {} |] `shouldRespondWith` "[]" { matchStatus = 200, matchHeaders = ["Content-Range" <:> "*/*"] } - get "/items" `shouldRespondWith` - [json| [{"id":3},{"id":4},{"id":5},{"id":6},{"id":7},{"id":8},{"id":9},{"id":10},{"id":11},{"id":12},{"id":13},{"id":14},{"id":15},{id:16},{"id":2},{"id":1}] |] - { matchHeaders = [matchContentTypeJson] } context "with unicode values" $ it "succeeds and returns values intact" $ do