feat: undefined json keys as defaults w/ Prefer:undefined-keys
This commit is contained in:
@@ -11,8 +11,9 @@ import Test.Hspec.Wai
|
||||
import Test.Hspec.Wai.JSON
|
||||
import Text.Heredoc
|
||||
|
||||
import PostgREST.Config.PgVersion (PgVersion, pgVersion110,
|
||||
pgVersion112, pgVersion130)
|
||||
import PostgREST.Config.PgVersion (PgVersion, pgVersion100,
|
||||
pgVersion110, pgVersion112,
|
||||
pgVersion130)
|
||||
|
||||
import Protolude hiding (get)
|
||||
import SpecHelper
|
||||
@@ -448,14 +449,64 @@ spec actualPgVersion = do
|
||||
{"id": 204, "body": "yyy"},
|
||||
333,
|
||||
"asdf",
|
||||
{"id": 205, "body": "zzz"}]|] `shouldRespondWith`
|
||||
[json|{
|
||||
"code": "22023",
|
||||
"details": null,
|
||||
"hint": null,
|
||||
"message": "argument of json_to_recordset must be an array of objects"}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = []
|
||||
{"id": 205, "body": "zzz"}]|] `shouldRespondWith` 400
|
||||
|
||||
context "apply defaults on undefined keys" $ do
|
||||
-- inserting the array fails on pg 9.6, but the feature should work normally
|
||||
when (actualPgVersion >= pgVersion100) $
|
||||
it "inserts table default values(field-with_sep) when json keys are undefined" $
|
||||
request methodPost "/complex_items?columns=id,name,field-with_sep,arr_data" [("Prefer", "return=representation"), ("Prefer", "undefined-keys=apply-defaults")]
|
||||
[json|[
|
||||
{"id": 4, "name": "Vier"},
|
||||
{"id": 5, "name": "Funf", "arr_data": null},
|
||||
{"id": 6, "name": "Sechs", "field-with_sep": 6, "arr_data": "{1,2,3}"}
|
||||
]|]
|
||||
`shouldRespondWith`
|
||||
[json|[
|
||||
{"id": 4, "name": "Vier", "field-with_sep": 1, "settings":null,"arr_data":null},
|
||||
{"id": 5, "name": "Funf", "field-with_sep": 1, "settings":null,"arr_data":null},
|
||||
{"id": 6, "name": "Sechs", "field-with_sep": 6, "settings":null,"arr_data":[1,2,3]}
|
||||
]|]
|
||||
{ matchStatus = 201
|
||||
, matchHeaders = ["Preference-Applied" <:> "undefined-keys=apply-defaults"]
|
||||
}
|
||||
|
||||
it "inserts view default values(field-with_sep) when json keys are undefined" $
|
||||
request methodPost "/complex_items_view?columns=id,name" [("Prefer", "return=representation"), ("Prefer", "undefined-keys=apply-defaults")]
|
||||
[json|[
|
||||
{"id": 7, "name": "Sieben"},
|
||||
{"id": 8}
|
||||
]|]
|
||||
`shouldRespondWith`
|
||||
[json|[
|
||||
{"id": 7, "name": "Sieben", "field-with_sep": 1, "settings":null,"arr_data":null},
|
||||
{"id": 8, "name": "Default", "field-with_sep": 1, "settings":null,"arr_data":null}
|
||||
]|]
|
||||
{ matchStatus = 201
|
||||
, matchHeaders = ["Preference-Applied" <:> "undefined-keys=apply-defaults"]
|
||||
}
|
||||
|
||||
it "doesn't insert json duplicate keys(since it uses jsonb)" $
|
||||
request methodPost "/tbl_w_json?columns=id,data" [("Prefer", "return=representation"), ("Prefer", "undefined-keys=apply-defaults")]
|
||||
[json| { "data": { "a": 1, "a": 2 }, "id": 3 } |]
|
||||
`shouldRespondWith`
|
||||
[json| [ { "data": { "a": 2 }, "id": 3 } ] |]
|
||||
{ matchStatus = 201
|
||||
, matchHeaders = ["Preference-Applied" <:> "undefined-keys=apply-defaults"]
|
||||
}
|
||||
|
||||
it "inserts json that has duplicate keys" $ do
|
||||
request methodPost "/tbl_w_json" [("Prefer", "return=representation")]
|
||||
[json| { "data": { "a": 1, "a": 2 }, "id": 3 } |]
|
||||
`shouldRespondWith`
|
||||
[json| [ { "data": { "a": 1, "a": 2 }, "id": 3 } ] |]
|
||||
{ matchStatus = 201
|
||||
}
|
||||
request methodPost "/tbl_w_json?columns=id,data" [("Prefer", "return=representation")]
|
||||
[json| { "data": { "a": 1, "a": 2 }, "id": 3 } |]
|
||||
`shouldRespondWith`
|
||||
[json| [ { "data": { "a": 1, "a": 2 }, "id": 3 } ] |]
|
||||
{ matchStatus = 201
|
||||
}
|
||||
|
||||
context "with unicode values" $ do
|
||||
|
||||
@@ -327,11 +327,11 @@ spec actualPgVersion = do
|
||||
describe "Shaping response with select parameter" $ do
|
||||
it "selectStar works in absense of parameter" $
|
||||
get "/complex_items?id=eq.3" `shouldRespondWith`
|
||||
[json|[{"id":3,"name":"Three","settings":{"foo":{"int":1,"bar":"baz"}},"arr_data":[1,2,3],"field-with_sep":1}]|]
|
||||
[json|[{"id":3,"name":"Three","settings":{"foo":{"int":1,"bar":"baz"}},"arr_data":[1,2,3],"field-with_sep":3}]|]
|
||||
|
||||
it "dash `-` in column names is accepted" $
|
||||
get "/complex_items?id=eq.3&select=id,field-with_sep" `shouldRespondWith`
|
||||
[json|[{"id":3,"field-with_sep":1}]|]
|
||||
[json|[{"id":3,"field-with_sep":3}]|]
|
||||
|
||||
it "one simple column" $
|
||||
get "/complex_items?select=id" `shouldRespondWith`
|
||||
|
||||
@@ -330,6 +330,57 @@ spec = do
|
||||
, matchHeaders = []
|
||||
}
|
||||
|
||||
context "apply defaults on undefined keys" $ do
|
||||
it "updates table using default values(field-with_sep) when json keys are undefined" $ do
|
||||
request methodPatch "/complex_items?id=eq.3&columns=name,field-with_sep"
|
||||
[("Prefer", "return=representation"), ("Prefer", "undefined-keys=apply-defaults")]
|
||||
[json|{"name": "Tres"}|]
|
||||
`shouldRespondWith`
|
||||
[json|[
|
||||
{"id":3,"name":"Tres","settings":{"foo":{"int":1,"bar":"baz"}},"arr_data":[1,2,3],"field-with_sep":1}
|
||||
]|]
|
||||
{ matchStatus = 200
|
||||
, matchHeaders = ["Preference-Applied" <:> "undefined-keys=apply-defaults"]
|
||||
}
|
||||
|
||||
it "updates with limit/offset using table default values(field-with_sep) when json keys are undefined" $ do
|
||||
request methodPatch "/complex_items?select=id,name&columns=name,field-with_sep&limit=1&offset=2&order=id"
|
||||
[("Prefer", "return=representation"), ("Prefer", "undefined-keys=apply-defaults")]
|
||||
[json|{"name": "Tres"}|]
|
||||
`shouldRespondWith`
|
||||
[json|[
|
||||
{"id":3,"name":"Tres"}
|
||||
]|]
|
||||
{ matchStatus = 200
|
||||
, matchHeaders = ["Preference-Applied" <:> "undefined-keys=apply-defaults"]
|
||||
}
|
||||
|
||||
it "updates table default values(field-with_sep) when json keys are undefined" $ do
|
||||
request methodPatch "/complex_items?id=eq.3&columns=name,field-with_sep"
|
||||
[("Prefer", "return=representation"), ("Prefer", "undefined-keys=apply-defaults")]
|
||||
[json|{"name": "Tres"}|]
|
||||
`shouldRespondWith`
|
||||
[json|[
|
||||
{"id":3,"name":"Tres","settings":{"foo":{"int":1,"bar":"baz"}},"arr_data":[1,2,3],"field-with_sep":1}
|
||||
]|]
|
||||
{ matchStatus = 200
|
||||
, matchHeaders = ["Preference-Applied" <:> "undefined-keys=apply-defaults"]
|
||||
}
|
||||
|
||||
it "updates view default values(field-with_sep) when json keys are undefined" $
|
||||
request methodPatch "/complex_items_view?id=eq.3&columns=arr_data,name"
|
||||
[("Prefer", "return=representation"), ("Prefer", "undefined-keys=apply-defaults")]
|
||||
[json|
|
||||
{"arr_data":null}
|
||||
|]
|
||||
`shouldRespondWith`
|
||||
[json|[
|
||||
{"id":3,"name":"Default","settings":{"foo":{"int":1,"bar":"baz"}},"arr_data":null,"field-with_sep":3}
|
||||
]|]
|
||||
{ matchStatus = 200
|
||||
, matchHeaders = ["Preference-Applied" <:> "undefined-keys=apply-defaults"]
|
||||
}
|
||||
|
||||
context "tables with self reference foreign keys" $ do
|
||||
it "embeds children after update" $
|
||||
request methodPatch "/web_content?id=eq.0&select=id,name,web_content(name)"
|
||||
|
||||
Vendored
+1
-1
@@ -168,7 +168,7 @@ INSERT INTO touched_files VALUES
|
||||
TRUNCATE TABLE complex_items CASCADE;
|
||||
INSERT INTO complex_items VALUES (1, 'One', '{"foo":{"int":1,"bar":"baz"}}', '{1}');
|
||||
INSERT INTO complex_items VALUES (2, 'Two', '{"foo":{"int":1,"bar":"baz"}}', '{1,2}');
|
||||
INSERT INTO complex_items VALUES (3, 'Three', '{"foo":{"int":1,"bar":"baz"}}', '{1,2,3}');
|
||||
INSERT INTO complex_items VALUES (3, 'Three', '{"foo":{"int":1,"bar":"baz"}}', '{1,2,3}', 3);
|
||||
|
||||
|
||||
--
|
||||
|
||||
Vendored
+10
@@ -3100,3 +3100,13 @@ create view test.alpha_projects as
|
||||
create view test.zeta_projects as
|
||||
select c.id, p.name as pro_name, c.name as cli_name
|
||||
from projects p join clients c on p.client_id = c.id;
|
||||
|
||||
CREATE VIEW test.complex_items_view AS
|
||||
SELECT * FROM test.complex_items;
|
||||
|
||||
ALTER VIEW test.complex_items_view ALTER COLUMN name SET DEFAULT 'Default';
|
||||
|
||||
create table test.tbl_w_json(
|
||||
id int,
|
||||
data json
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user