Add 'PGRST' error code to differentiate from PostgreSQL errors
This commit is contained in:
@@ -201,7 +201,9 @@ spec actualPgVersion =
|
||||
get "/entities?or=()" `shouldRespondWith`
|
||||
[json|{
|
||||
"details": "unexpected \")\" expecting field name (* or [a..z0..9_]), negation operator (not) or logic operator (and, or)",
|
||||
"message": "\"failed to parse logic tree (())\" (line 1, column 4)"
|
||||
"message": "\"failed to parse logic tree (())\" (line 1, column 4)",
|
||||
"code": "PGRST100",
|
||||
"hint": null
|
||||
}|] { matchStatus = 400, matchHeaders = [matchContentTypeJson] }
|
||||
it "can have a single condition" $ do
|
||||
get "/entities?or=(id.eq.1)&select=id" `shouldRespondWith`
|
||||
@@ -255,22 +257,30 @@ spec actualPgVersion =
|
||||
get "/entities?or=(id.in.1,2,id.eq.3)" `shouldRespondWith`
|
||||
[json|{
|
||||
"details": "unexpected \"1\" expecting \"(\"",
|
||||
"message": "\"failed to parse logic tree ((id.in.1,2,id.eq.3))\" (line 1, column 10)"
|
||||
"message": "\"failed to parse logic tree ((id.in.1,2,id.eq.3))\" (line 1, column 10)",
|
||||
"code": "PGRST100",
|
||||
"hint": null
|
||||
}|] { matchStatus = 400, matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "fails on malformed query params and provides meaningful error message" $ do
|
||||
get "/entities?or=)(" `shouldRespondWith`
|
||||
[json|{
|
||||
"details": "unexpected \")\" expecting \"(\"",
|
||||
"message": "\"failed to parse logic tree ()()\" (line 1, column 3)"
|
||||
"message": "\"failed to parse logic tree ()()\" (line 1, column 3)",
|
||||
"code": "PGRST100",
|
||||
"hint": null
|
||||
}|] { matchStatus = 400, matchHeaders = [matchContentTypeJson] }
|
||||
get "/entities?and=(ord(id.eq.1,id.eq.1),id.eq.2)" `shouldRespondWith`
|
||||
[json|{
|
||||
"details": "unexpected \"d\" expecting \"(\"",
|
||||
"message": "\"failed to parse logic tree ((ord(id.eq.1,id.eq.1),id.eq.2))\" (line 1, column 7)"
|
||||
"message": "\"failed to parse logic tree ((ord(id.eq.1,id.eq.1),id.eq.2))\" (line 1, column 7)",
|
||||
"code": "PGRST100",
|
||||
"hint": null
|
||||
}|] { matchStatus = 400, matchHeaders = [matchContentTypeJson] }
|
||||
get "/entities?or=(id.eq.1,not.xor(id.eq.2,id.eq.3))" `shouldRespondWith`
|
||||
[json|{
|
||||
"details": "unexpected \"x\" expecting logic operator (and, or)",
|
||||
"message": "\"failed to parse logic tree ((id.eq.1,not.xor(id.eq.2,id.eq.3)))\" (line 1, column 16)"
|
||||
"message": "\"failed to parse logic tree ((id.eq.1,not.xor(id.eq.2,id.eq.3)))\" (line 1, column 16)",
|
||||
"code": "PGRST100",
|
||||
"hint": null
|
||||
}|] { matchStatus = 400, matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
@@ -30,7 +30,8 @@ spec =
|
||||
}
|
||||
],
|
||||
"hint": "Try changing 'sender' to one of the following: 'person!message_sender_fkey', 'person_detail!message_sender_fkey'. Find the desired relationship in the 'details' key.",
|
||||
"message": "Could not embed because more than one relationship was found for 'message' and 'sender'"
|
||||
"message": "Could not embed because more than one relationship was found for 'message' and 'sender'",
|
||||
"code": "PGRST201"
|
||||
}
|
||||
|]
|
||||
{ matchStatus = 300
|
||||
@@ -59,7 +60,8 @@ spec =
|
||||
}
|
||||
],
|
||||
"hint": "Try changing 'big_projects' to one of the following: 'big_projects!main_project', 'big_projects!jobs', 'big_projects!main_jobs'. Find the desired relationship in the 'details' key.",
|
||||
"message": "Could not embed because more than one relationship was found for 'sites' and 'big_projects'"
|
||||
"message": "Could not embed because more than one relationship was found for 'sites' and 'big_projects'",
|
||||
"code": "PGRST201"
|
||||
}
|
||||
|]
|
||||
{ matchStatus = 300
|
||||
@@ -83,7 +85,8 @@ spec =
|
||||
}
|
||||
],
|
||||
"hint": "Try changing 'departments' to one of the following: 'departments!agents_department_id_fkey', 'departments!departments_head_id_fkey'. Find the desired relationship in the 'details' key.",
|
||||
"message": "Could not embed because more than one relationship was found for 'agents' and 'departments'"
|
||||
"message": "Could not embed because more than one relationship was found for 'agents' and 'departments'",
|
||||
"code": "PGRST201"
|
||||
}
|
||||
|]
|
||||
{ matchStatus = 300
|
||||
@@ -120,7 +123,8 @@ spec =
|
||||
}
|
||||
],
|
||||
"hint": "Try changing 'whatev_projects' to one of the following: 'whatev_projects!whatev_jobs', 'whatev_projects!whatev_jobs', 'whatev_projects!whatev_jobs', 'whatev_projects!whatev_jobs'. Find the desired relationship in the 'details' key.",
|
||||
"message": "Could not embed because more than one relationship was found for 'whatev_sites' and 'whatev_projects'"
|
||||
"message": "Could not embed because more than one relationship was found for 'whatev_sites' and 'whatev_projects'",
|
||||
"code": "PGRST201"
|
||||
}
|
||||
|]
|
||||
{ matchStatus = 300
|
||||
@@ -175,7 +179,9 @@ spec =
|
||||
get "/message?select=id,sender:person!space(name)&id=lt.4" `shouldRespondWith`
|
||||
[json|{
|
||||
"hint":"Verify that 'message' and 'person' exist in the schema 'test' and that there is a foreign key relationship between them. If a new relationship was created, try reloading the schema cache.",
|
||||
"message":"Could not find a relationship between 'message' and 'person' in the schema cache"}|]
|
||||
"message":"Could not find a relationship between 'message' and 'person' in the schema cache",
|
||||
"code": "PGRST200",
|
||||
"details": null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
@@ -426,7 +432,9 @@ spec =
|
||||
get "/end_1?select=end_2(*)" `shouldRespondWith`
|
||||
[json|{
|
||||
"hint":"Verify that 'end_1' and 'end_2' exist in the schema 'test' and that there is a foreign key relationship between them. If a new relationship was created, try reloading the schema cache.",
|
||||
"message":"Could not find a relationship between 'end_1' and 'end_2' in the schema cache"}|]
|
||||
"message":"Could not find a relationship between 'end_1' and 'end_2' in the schema cache",
|
||||
"code":"PGRST200",
|
||||
"details": null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson] }
|
||||
it "shouldn't try to embed if the private junction has an exposed homonym" $
|
||||
@@ -435,6 +443,8 @@ spec =
|
||||
get "/schauspieler?select=filme(*)" `shouldRespondWith`
|
||||
[json|{
|
||||
"hint":"Verify that 'schauspieler' and 'filme' exist in the schema 'test' and that there is a foreign key relationship between them. If a new relationship was created, try reloading the schema cache.",
|
||||
"message":"Could not find a relationship between 'schauspieler' and 'filme' in the schema cache"}|]
|
||||
"message":"Could not find a relationship between 'schauspieler' and 'filme' in the schema cache",
|
||||
"code":"PGRST200",
|
||||
"details": null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
@@ -24,7 +24,11 @@ spec = do
|
||||
[]
|
||||
""
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Unsupported HTTP verb: CONNECT"}|]
|
||||
[json|
|
||||
{"hint": null,
|
||||
"details": null,
|
||||
"code": "PGRST506",
|
||||
"message":"Unsupported HTTP verb: CONNECT"}|]
|
||||
{ matchStatus = 405 }
|
||||
|
||||
it "should return 405 for TRACE method" $
|
||||
@@ -32,7 +36,11 @@ spec = do
|
||||
[]
|
||||
""
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Unsupported HTTP verb: TRACE"}|]
|
||||
[json|
|
||||
{"hint": null,
|
||||
"details": null,
|
||||
"code": "PGRST506",
|
||||
"message":"Unsupported HTTP verb: TRACE"}|]
|
||||
{ matchStatus = 405 }
|
||||
|
||||
it "should return 405 for OTHER method" $
|
||||
@@ -40,5 +48,9 @@ spec = do
|
||||
[]
|
||||
""
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Unsupported HTTP verb: OTHER"}|]
|
||||
[json|
|
||||
{"hint": null,
|
||||
"details": null,
|
||||
"code": "PGRST506",
|
||||
"message":"Unsupported HTTP verb: OTHER"}|]
|
||||
{ matchStatus = 405 }
|
||||
|
||||
@@ -75,7 +75,7 @@ spec actualPgVersion = do
|
||||
post "/articles"
|
||||
[json| [{"id": 100, "body": "xxxxx"}, 123, "xxxx", {"id": 111, "body": "xxxx"}] |]
|
||||
`shouldRespondWith`
|
||||
[json| {"message":"All object keys must match"} |]
|
||||
[json| {"message":"All object keys must match","code":"PGRST102","hint":null,"details":null} |]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -84,7 +84,7 @@ spec actualPgVersion = do
|
||||
post "/articles"
|
||||
[json| [{"id": 100, "body": "xxxxx"}, {"id": 111, "body": "xxxx", "owner": "me"}] |]
|
||||
`shouldRespondWith`
|
||||
[json| {"message":"All object keys must match"} |]
|
||||
[json| {"message":"All object keys must match","code":"PGRST102","hint":null,"details":null} |]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -276,7 +276,7 @@ spec actualPgVersion = do
|
||||
it "fails with 400 and error" $
|
||||
post "/simple_pk" "}{ x = 2"
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Error in $: Failed reading: not a valid json value at '}{x=2'"}|]
|
||||
[json|{"message":"Error in $: Failed reading: not a valid json value at '}{x=2'","code":"PGRST102","details":null,"hint":null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -285,7 +285,7 @@ spec actualPgVersion = do
|
||||
it "fails with 400 and error" $
|
||||
post "/simple_pk" ""
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Error in $: not enough input"}|]
|
||||
[json|{"message":"Error in $: not enough input","code":"PGRST102","details":null,"hint":null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -415,7 +415,7 @@ spec actualPgVersion = do
|
||||
{"id": 204, "body": "yyy"},
|
||||
{"id": 205, "body": "zzz"}]|]
|
||||
`shouldRespondWith`
|
||||
[json| {"details":"unexpected end of input expecting field name (* or [a..z0..9_])","message":"\"failed to parse columns parameter ()\" (line 1, column 1)"} |]
|
||||
[json| {"details":"unexpected end of input expecting field name (* or [a..z0..9_])","message":"\"failed to parse columns parameter ()\" (line 1, column 1)","code":"PGRST100","hint":null} |]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = []
|
||||
}
|
||||
@@ -484,7 +484,7 @@ spec actualPgVersion = do
|
||||
it "fails for too few" $
|
||||
request methodPost "/no_pk" [("Content-Type", "text/csv")] "a,b\nfoo,bar\nbaz"
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"All lines must have same number of fields"}|]
|
||||
[json|{"message":"All lines must have same number of fields","code":"PGRST102","details":null,"hint":null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
|
||||
@@ -296,15 +296,21 @@ spec actualPgVersion = describe "json and jsonb operators" $ do
|
||||
get "/json_arr?select=data->>-78xy" `shouldRespondWith`
|
||||
[json|
|
||||
{"details": "unexpected 'x' expecting digit, \"->\", \"::\", \".\", \",\" or end of input",
|
||||
"message": "\"failed to parse select parameter (data->>-78xy)\" (line 1, column 11)"} |]
|
||||
"message": "\"failed to parse select parameter (data->>-78xy)\" (line 1, column 11)",
|
||||
"code": "PGRST100",
|
||||
"hint": null} |]
|
||||
{ matchStatus = 400, matchHeaders = [matchContentTypeJson] }
|
||||
get "/json_arr?select=data->>--34" `shouldRespondWith`
|
||||
[json|
|
||||
{"details": "unexpected \"-\" expecting digit",
|
||||
"message": "\"failed to parse select parameter (data->>--34)\" (line 1, column 9)"} |]
|
||||
"message": "\"failed to parse select parameter (data->>--34)\" (line 1, column 9)",
|
||||
"code": "PGRST100",
|
||||
"hint": null} |]
|
||||
{ matchStatus = 400, matchHeaders = [matchContentTypeJson] }
|
||||
get "/json_arr?select=data->>-xy-4" `shouldRespondWith`
|
||||
[json|
|
||||
{"details":"unexpected \"x\" expecting digit",
|
||||
"message":"\"failed to parse select parameter (data->>-xy-4)\" (line 1, column 9)"} |]
|
||||
"message":"\"failed to parse select parameter (data->>-xy-4)\" (line 1, column 9)",
|
||||
"code": "PGRST100",
|
||||
"hint": null} |]
|
||||
{ matchStatus = 400, matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
@@ -68,7 +68,7 @@ spec =
|
||||
|
||||
it "fails trying to read table from unkown schema" $
|
||||
request methodGet "/parents" [("Accept-Profile", "unkown")] "" `shouldRespondWith`
|
||||
[json|{"message":"The schema must be one of the following: v1, v2"}|]
|
||||
[json|{"message":"The schema must be one of the following: v1, v2","code":"PGRST106","details":null,"hint":null}|]
|
||||
{
|
||||
matchStatus = 406
|
||||
}
|
||||
@@ -111,7 +111,7 @@ spec =
|
||||
request methodPost "/children" [("Content-Profile", "unknown")]
|
||||
[json|{"name": "child 4", "parent_id": 4}|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"The schema must be one of the following: v1, v2"}|]
|
||||
[json|{"message":"The schema must be one of the following: v1, v2","code":"PGRST106","details":null,"hint":null}|]
|
||||
{
|
||||
matchStatus = 406
|
||||
}
|
||||
@@ -325,7 +325,7 @@ spec =
|
||||
|
||||
it "fails trying to read definitions from unkown schema" $
|
||||
request methodGet "/" [("Accept-Profile", "unkown")] "" `shouldRespondWith`
|
||||
[json|{"message":"The schema must be one of the following: v1, v2"}|]
|
||||
[json|{"message":"The schema must be one of the following: v1, v2","code":"PGRST106","details":null,"hint":null}|]
|
||||
{
|
||||
matchStatus = 406
|
||||
}
|
||||
|
||||
@@ -266,13 +266,17 @@ spec actualPgVersion = do
|
||||
get "/clients?select=*&non_existent_projects.name=like.*NonExistent*" `shouldRespondWith`
|
||||
[json|
|
||||
{"hint":"Verify that 'non_existent_projects' is included in the 'select' query parameter.",
|
||||
"message":"Cannot apply filter because 'non_existent_projects' is not an embedded resource in this request"}|]
|
||||
"details":null,
|
||||
"code":"PGRST108",
|
||||
"message":"Cannot apply filter because 'non_existent_projects' is not an embedded resource in this request"}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
get "/clients?select=*,amiga_projects:projects(*)&amiga_projectsss.name=ilike.*Amiga*" `shouldRespondWith`
|
||||
[json|
|
||||
{"hint":"Verify that 'amiga_projectsss' is included in the 'select' query parameter.",
|
||||
"details":null,
|
||||
"code":"PGRST108",
|
||||
"message":"Cannot apply filter because 'amiga_projectsss' is not an embedded resource in this request"}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
@@ -280,6 +284,8 @@ spec actualPgVersion = do
|
||||
get "/clients?select=id,projects(id,tasks(id,name))&projects.tasks2.name=like.Design*" `shouldRespondWith`
|
||||
[json|
|
||||
{"hint":"Verify that 'tasks2' is included in the 'select' query parameter.",
|
||||
"details":null,
|
||||
"code":"PGRST108",
|
||||
"message":"Cannot apply filter because 'tasks2' is not an embedded resource in this request"}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
@@ -504,6 +510,8 @@ spec actualPgVersion = do
|
||||
get "/car_models?id=in.(1,2,4)&select=id,name,car_model_sales_202101(id)&order=id.asc" `shouldRespondWith`
|
||||
[json|
|
||||
{"hint":"Verify that 'car_models' and 'car_model_sales_202101' exist in the schema 'test' and that there is a foreign key relationship between them. If a new relationship was created, try reloading the schema cache.",
|
||||
"details":null,
|
||||
"code":"PGRST200",
|
||||
"message":"Could not find a relationship between 'car_models' and 'car_model_sales_202101' in the schema cache"} |]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
@@ -513,6 +521,8 @@ spec actualPgVersion = do
|
||||
get "/car_model_sales_202101?select=id,name,car_models(id,name)&order=id.asc" `shouldRespondWith`
|
||||
[json|
|
||||
{"hint":"Verify that 'car_model_sales_202101' and 'car_models' exist in the schema 'test' and that there is a foreign key relationship between them. If a new relationship was created, try reloading the schema cache.",
|
||||
"details":null,
|
||||
"code":"PGRST200",
|
||||
"message":"Could not find a relationship between 'car_model_sales_202101' and 'car_models' in the schema cache"} |]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
@@ -522,6 +532,8 @@ spec actualPgVersion = do
|
||||
get "/car_model_sales?id=in.(1,3,4)&select=id,name,car_models_default(id,name)&order=id.asc" `shouldRespondWith`
|
||||
[json|
|
||||
{"hint":"Verify that 'car_model_sales' and 'car_models_default' exist in the schema 'test' and that there is a foreign key relationship between them. If a new relationship was created, try reloading the schema cache.",
|
||||
"details":null,
|
||||
"code":"PGRST200",
|
||||
"message":"Could not find a relationship between 'car_model_sales' and 'car_models_default' in the schema cache"} |]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
@@ -531,6 +543,8 @@ spec actualPgVersion = do
|
||||
get "/car_models_default?select=id,name,car_model_sales(id,name)&order=id.asc" `shouldRespondWith`
|
||||
[json|
|
||||
{"hint":"Verify that 'car_models_default' and 'car_model_sales' exist in the schema 'test' and that there is a foreign key relationship between them. If a new relationship was created, try reloading the schema cache.",
|
||||
"details":null,
|
||||
"code":"PGRST200",
|
||||
"message":"Could not find a relationship between 'car_models_default' and 'car_model_sales' in the schema cache"} |]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
@@ -812,44 +826,44 @@ spec actualPgVersion = do
|
||||
context "order syntax errors" $ do
|
||||
it "gives meaningful error messages when asc/desc/nulls{first,last} are misspelled" $ do
|
||||
get "/items?order=id.ac" `shouldRespondWith`
|
||||
[json|{"details":"unexpected \"c\" expecting \"asc\", \"desc\", \"nullsfirst\" or \"nullslast\"","message":"\"failed to parse order (id.ac)\" (line 1, column 4)"}|]
|
||||
[json|{"details":"unexpected \"c\" expecting \"asc\", \"desc\", \"nullsfirst\" or \"nullslast\"","message":"\"failed to parse order (id.ac)\" (line 1, column 4)","code":"PGRST100","hint":null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
get "/items?order=id.descc" `shouldRespondWith`
|
||||
[json|{"details":"unexpected 'c' expecting delimiter (.), \",\" or end of input","message":"\"failed to parse order (id.descc)\" (line 1, column 8)"}|]
|
||||
[json|{"details":"unexpected 'c' expecting delimiter (.), \",\" or end of input","message":"\"failed to parse order (id.descc)\" (line 1, column 8)","code":"PGRST100","hint":null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
get "/items?order=id.nulsfist" `shouldRespondWith`
|
||||
[json|{"details":"unexpected \"n\" expecting \"asc\", \"desc\", \"nullsfirst\" or \"nullslast\"","message":"\"failed to parse order (id.nulsfist)\" (line 1, column 4)"}|]
|
||||
[json|{"details":"unexpected \"n\" expecting \"asc\", \"desc\", \"nullsfirst\" or \"nullslast\"","message":"\"failed to parse order (id.nulsfist)\" (line 1, column 4)","code":"PGRST100","hint":null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
get "/items?order=id.nullslasttt" `shouldRespondWith`
|
||||
[json|{"details":"unexpected 't' expecting \",\" or end of input","message":"\"failed to parse order (id.nullslasttt)\" (line 1, column 13)"}|]
|
||||
[json|{"details":"unexpected 't' expecting \",\" or end of input","message":"\"failed to parse order (id.nullslasttt)\" (line 1, column 13)","code":"PGRST100","hint":null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
get "/items?order=id.smth34" `shouldRespondWith`
|
||||
[json|{"details":"unexpected \"s\" expecting \"asc\", \"desc\", \"nullsfirst\" or \"nullslast\"","message":"\"failed to parse order (id.smth34)\" (line 1, column 4)"}|]
|
||||
[json|{"details":"unexpected \"s\" expecting \"asc\", \"desc\", \"nullsfirst\" or \"nullslast\"","message":"\"failed to parse order (id.smth34)\" (line 1, column 4)","code":"PGRST100","hint":null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
|
||||
it "gives meaningful error messages when nulls{first,last} are misspelled after asc/desc" $ do
|
||||
get "/items?order=id.asc.nlsfst" `shouldRespondWith`
|
||||
[json|{"details":"unexpected \"l\" expecting \"nullsfirst\" or \"nullslast\"","message":"\"failed to parse order (id.asc.nlsfst)\" (line 1, column 8)"}|]
|
||||
[json|{"details":"unexpected \"l\" expecting \"nullsfirst\" or \"nullslast\"","message":"\"failed to parse order (id.asc.nlsfst)\" (line 1, column 8)","code":"PGRST100","hint":null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
get "/items?order=id.asc.nullslasttt" `shouldRespondWith`
|
||||
[json|{"details":"unexpected 't' expecting \",\" or end of input","message":"\"failed to parse order (id.asc.nullslasttt)\" (line 1, column 17)"}|]
|
||||
[json|{"details":"unexpected 't' expecting \",\" or end of input","message":"\"failed to parse order (id.asc.nullslasttt)\" (line 1, column 17)","code":"PGRST100","hint":null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
get "/items?order=id.asc.smth34" `shouldRespondWith`
|
||||
[json|{"details":"unexpected \"s\" expecting \"nullsfirst\" or \"nullslast\"","message":"\"failed to parse order (id.asc.smth34)\" (line 1, column 8)"}|]
|
||||
[json|{"details":"unexpected \"s\" expecting \"nullsfirst\" or \"nullslast\"","message":"\"failed to parse order (id.asc.smth34)\" (line 1, column 8)","code":"PGRST100","hint":null}|]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -859,7 +873,7 @@ spec actualPgVersion = do
|
||||
request methodGet "/simple_pk"
|
||||
(acceptHdrs "text/unknowntype") ""
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"None of these Content-Types are available: text/unknowntype"}|]
|
||||
[json|{"message":"None of these Content-Types are available: text/unknowntype","code":"PGRST107","details":null,"hint":null}|]
|
||||
{ matchStatus = 415
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -928,7 +942,7 @@ spec actualPgVersion = do
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "fails if an operator is not given" $
|
||||
get "/ghostBusters?id=0" `shouldRespondWith` [json| {"details":"Failed to parse [(\"id\",\"0\")]","message":"Unexpected param or filter missing operator"} |]
|
||||
get "/ghostBusters?id=0" `shouldRespondWith` [json| {"details":"Failed to parse [(\"id\",\"0\")]","message":"Unexpected param or filter missing operator","code":"PGRST104","hint":null} |]
|
||||
{ matchStatus = 400
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -970,21 +984,21 @@ spec actualPgVersion = do
|
||||
it "fails if a single column is not selected" $ do
|
||||
request methodGet "/images?select=img,name&name=eq.A.png" (acceptHdrs "application/octet-stream") ""
|
||||
`shouldRespondWith`
|
||||
[json| {"message":"application/octet-stream requested but more than one column was selected"} |]
|
||||
[json| {"message":"application/octet-stream requested but more than one column was selected","code":"PGRST502","details":null,"hint":null} |]
|
||||
{ matchStatus = 406 }
|
||||
|
||||
request methodGet "/images?select=*&name=eq.A.png"
|
||||
(acceptHdrs "application/octet-stream")
|
||||
""
|
||||
`shouldRespondWith`
|
||||
[json| {"message":"application/octet-stream requested but more than one column was selected"} |]
|
||||
[json| {"message":"application/octet-stream requested but more than one column was selected","code":"PGRST502","details":null,"hint":null} |]
|
||||
{ matchStatus = 406 }
|
||||
|
||||
request methodGet "/images?name=eq.A.png"
|
||||
(acceptHdrs "application/octet-stream")
|
||||
""
|
||||
`shouldRespondWith`
|
||||
[json| {"message":"application/octet-stream requested but more than one column was selected"} |]
|
||||
[json| {"message":"application/octet-stream requested but more than one column was selected","code":"PGRST502","details":null,"hint":null} |]
|
||||
{ matchStatus = 406 }
|
||||
|
||||
it "concatenates results if more than one row is returned" $
|
||||
|
||||
@@ -186,14 +186,14 @@ spec = do
|
||||
|
||||
it "fails if limit equals 0" $
|
||||
get "/items?select=id&limit=0"
|
||||
`shouldRespondWith` [json|{"message":"HTTP Range error"}|]
|
||||
`shouldRespondWith` [json|{"message":"HTTP Range error","code":"PGRST103","details":null,"hint":null}|]
|
||||
{ matchStatus = 416
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
|
||||
it "fails if limit is negative" $
|
||||
get "/items?select=id&limit=-1"
|
||||
`shouldRespondWith` [json|{"message":"HTTP Range error"}|]
|
||||
`shouldRespondWith` [json|{"message":"HTTP Range error","code":"PGRST103","details":null,"hint":null}|]
|
||||
{ matchStatus = 416
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
|
||||
@@ -114,7 +114,9 @@ spec actualPgVersion =
|
||||
get "/rpc/add_them?a=1&b=2&smthelse=blabla" `shouldRespondWith`
|
||||
[json| {
|
||||
"hint":"If a new function was created in the database with this name and parameters, try reloading the schema cache.",
|
||||
"message":"Could not find the test.add_them(a, b, smthelse) function in the schema cache" } |]
|
||||
"message":"Could not find the test.add_them(a, b, smthelse) function in the schema cache",
|
||||
"code":"PGRST202",
|
||||
"details":null} |]
|
||||
{ matchStatus = 404
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -126,7 +128,9 @@ spec actualPgVersion =
|
||||
`shouldRespondWith`
|
||||
[json| {
|
||||
"hint":"If a new function was created in the database with this name and parameters, try reloading the schema cache.",
|
||||
"message":"Could not find the test.sayhello function with a single json or jsonb parameter in the schema cache" } |]
|
||||
"message":"Could not find the test.sayhello function with a single json or jsonb parameter in the schema cache",
|
||||
"code":"PGRST202",
|
||||
"details":null} |]
|
||||
{ matchStatus = 404
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -135,14 +139,18 @@ spec actualPgVersion =
|
||||
get "/rpc/overloaded?wrong_arg=value" `shouldRespondWith`
|
||||
[json| {
|
||||
"hint":"If a new function was created in the database with this name and parameters, try reloading the schema cache.",
|
||||
"message":"Could not find the test.overloaded(wrong_arg) function in the schema cache" } |]
|
||||
"message":"Could not find the test.overloaded(wrong_arg) function in the schema cache",
|
||||
"code":"PGRST202",
|
||||
"details":null} |]
|
||||
{ matchStatus = 404
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
get "/rpc/overloaded?a=1&b=2&wrong_arg=value" `shouldRespondWith`
|
||||
[json| {
|
||||
"hint":"If a new function was created in the database with this name and parameters, try reloading the schema cache.",
|
||||
"message":"Could not find the test.overloaded(a, b, wrong_arg) function in the schema cache" } |]
|
||||
"message":"Could not find the test.overloaded(a, b, wrong_arg) function in the schema cache",
|
||||
"code":"PGRST202",
|
||||
"details":null} |]
|
||||
{ matchStatus = 404
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -152,7 +160,9 @@ spec actualPgVersion =
|
||||
get "/rpc/overloaded_same_args?arg=value" `shouldRespondWith`
|
||||
[json| {
|
||||
"hint":"Try renaming the parameters or the function itself in the database so function overloading can be resolved",
|
||||
"message":"Could not choose the best candidate function between: test.overloaded_same_args(arg => integer), test.overloaded_same_args(arg => xml), test.overloaded_same_args(arg => text, num => integer)"}|]
|
||||
"message":"Could not choose the best candidate function between: test.overloaded_same_args(arg => integer), test.overloaded_same_args(arg => xml), test.overloaded_same_args(arg => text, num => integer)",
|
||||
"code":"PGRST203",
|
||||
"details":null} |]
|
||||
{ matchStatus = 300
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -510,7 +520,7 @@ spec actualPgVersion =
|
||||
it "DELETE fails" $
|
||||
request methodDelete "/rpc/sayhello" [] ""
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Bad Request"}|]
|
||||
[json|{"message":"Bad Request","code":"PGRST101","details":null,"hint":null}|]
|
||||
{ matchStatus = 405
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -671,7 +681,7 @@ spec actualPgVersion =
|
||||
|
||||
it "can map a RAISE error code and message to a http status" $
|
||||
get "/rpc/raise_pt402"
|
||||
`shouldRespondWith` [json|{ "hint": "Upgrade your plan", "details": "Quota exceeded" }|]
|
||||
`shouldRespondWith` [json|{ "hint": "Upgrade your plan", "details": "Quota exceeded", "code": "PT402", "message": "Payment Required" }|]
|
||||
{ matchStatus = 402
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -679,7 +689,7 @@ spec actualPgVersion =
|
||||
it "defaults to status 500 if RAISE code is PT not followed by a number" $
|
||||
get "/rpc/raise_bad_pt"
|
||||
`shouldRespondWith`
|
||||
[json|{"hint": null, "details": null}|]
|
||||
[json|{"hint": null, "details": null, "code": "PT40A", "message": "Wrong"}|]
|
||||
{ matchStatus = 500
|
||||
, matchHeaders = [ matchContentTypeJson ]
|
||||
}
|
||||
@@ -983,7 +993,7 @@ spec actualPgVersion =
|
||||
request methodPost "/rpc/ret_rows_with_base64_bin"
|
||||
(acceptHdrs "application/octet-stream") ""
|
||||
`shouldRespondWith`
|
||||
[json| {"message":"application/octet-stream requested but more than one column was selected"} |]
|
||||
[json| {"message":"application/octet-stream requested but more than one column was selected","code":"PGRST502","details":null,"hint":null} |]
|
||||
{ matchStatus = 406 }
|
||||
|
||||
context "only for GET rpc" $ do
|
||||
@@ -1053,25 +1063,25 @@ spec actualPgVersion =
|
||||
it "fails when setting headers with wrong json structure" $ do
|
||||
get "/rpc/bad_guc_headers_1"
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"response.headers guc must be a JSON array composed of objects with a single key and a string value"}|]
|
||||
[json|{"message":"response.headers guc must be a JSON array composed of objects with a single key and a string value","code":"PGRST500","details":null,"hint":null}|]
|
||||
{ matchStatus = 500
|
||||
, matchHeaders = [ matchContentTypeJson ]
|
||||
}
|
||||
get "/rpc/bad_guc_headers_2"
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"response.headers guc must be a JSON array composed of objects with a single key and a string value"}|]
|
||||
[json|{"message":"response.headers guc must be a JSON array composed of objects with a single key and a string value","code":"PGRST500","details":null,"hint":null}|]
|
||||
{ matchStatus = 500
|
||||
, matchHeaders = [ matchContentTypeJson ]
|
||||
}
|
||||
get "/rpc/bad_guc_headers_3"
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"response.headers guc must be a JSON array composed of objects with a single key and a string value"}|]
|
||||
[json|{"message":"response.headers guc must be a JSON array composed of objects with a single key and a string value","code":"PGRST500","details":null,"hint":null}|]
|
||||
{ matchStatus = 500
|
||||
, matchHeaders = [ matchContentTypeJson ]
|
||||
}
|
||||
post "/rpc/bad_guc_headers_1" [json|{}|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"response.headers guc must be a JSON array composed of objects with a single key and a string value"}|]
|
||||
[json|{"message":"response.headers guc must be a JSON array composed of objects with a single key and a string value","code":"PGRST500","details":null,"hint":null}|]
|
||||
{ matchStatus = 500
|
||||
, matchHeaders = [ matchContentTypeJson ]
|
||||
}
|
||||
@@ -1142,7 +1152,7 @@ spec actualPgVersion =
|
||||
it "fails when setting invalid status guc" $
|
||||
get "/rpc/send_bad_status"
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"response.status guc must be a valid status code"}|]
|
||||
[json|{"message":"response.status guc must be a valid status code","code":"PGRST501","details":null,"hint":null}|]
|
||||
{ matchStatus = 500
|
||||
, matchHeaders = [ matchContentTypeJson ]
|
||||
}
|
||||
@@ -1176,7 +1186,9 @@ spec actualPgVersion =
|
||||
`shouldRespondWith`
|
||||
[json|{
|
||||
"hint": "If a new function was created in the database with this name and parameters, try reloading the schema cache.",
|
||||
"message": "Could not find the test.unnamed_int_param(x, y) function or the test.unnamed_int_param function with a single unnamed json or jsonb parameter in the schema cache"
|
||||
"message": "Could not find the test.unnamed_int_param(x, y) function or the test.unnamed_int_param function with a single unnamed json or jsonb parameter in the schema cache",
|
||||
"code":"PGRST202",
|
||||
"details":null
|
||||
}|]
|
||||
{ matchStatus = 404
|
||||
, matchHeaders = [ matchContentTypeJson ]
|
||||
@@ -1189,7 +1201,9 @@ spec actualPgVersion =
|
||||
`shouldRespondWith`
|
||||
[json|{
|
||||
"hint": "If a new function was created in the database with this name and parameters, try reloading the schema cache.",
|
||||
"message": "Could not find the test.unnamed_int_param function with a single unnamed text parameter in the schema cache"
|
||||
"message": "Could not find the test.unnamed_int_param function with a single unnamed text parameter in the schema cache",
|
||||
"code":"PGRST202",
|
||||
"details":null
|
||||
}|]
|
||||
{ matchStatus = 404
|
||||
, matchHeaders = [ matchContentTypeJson ]
|
||||
@@ -1203,7 +1217,9 @@ spec actualPgVersion =
|
||||
`shouldRespondWith`
|
||||
[json|{
|
||||
"hint": "If a new function was created in the database with this name and parameters, try reloading the schema cache.",
|
||||
"message": "Could not find the test.unnamed_int_param function with a single unnamed bytea parameter in the schema cache"
|
||||
"message": "Could not find the test.unnamed_int_param function with a single unnamed bytea parameter in the schema cache",
|
||||
"code":"PGRST202",
|
||||
"details":null
|
||||
}|]
|
||||
{ matchStatus = 404
|
||||
, matchHeaders = [ matchContentTypeJson ]
|
||||
@@ -1261,7 +1277,10 @@ spec actualPgVersion =
|
||||
`shouldRespondWith`
|
||||
[json| {
|
||||
"hint":"If a new function was created in the database with this name and parameters, try reloading the schema cache.",
|
||||
"message":"Could not find the test.overloaded_unnamed_param(a, b) function in the schema cache"}|]
|
||||
"message":"Could not find the test.overloaded_unnamed_param(a, b) function in the schema cache",
|
||||
"code":"PGRST202",
|
||||
"details":null
|
||||
}|]
|
||||
{ matchStatus = 404
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -1272,7 +1291,10 @@ spec actualPgVersion =
|
||||
`shouldRespondWith`
|
||||
[json| {
|
||||
"hint":"Try renaming the parameters or the function itself in the database so function overloading can be resolved",
|
||||
"message":"Could not choose the best candidate function between: test.overloaded_unnamed_json_jsonb_param( => json), test.overloaded_unnamed_json_jsonb_param( => jsonb)"}|]
|
||||
"message":"Could not choose the best candidate function between: test.overloaded_unnamed_json_jsonb_param( => json), test.overloaded_unnamed_json_jsonb_param( => jsonb)",
|
||||
"code":"PGRST203",
|
||||
"details":null
|
||||
}|]
|
||||
{ matchStatus = 300
|
||||
, matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ spec =
|
||||
[("Prefer", "tx=commit"), singular]
|
||||
[json| { address: "zzz" } |]
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 4 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 4 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [ matchContentTypeSingular
|
||||
, "Preference-Applied" <:> "tx=commit" ]
|
||||
@@ -85,7 +85,7 @@ spec =
|
||||
[("Prefer", "tx=commit"), ("Prefer", "return=representation"), singular]
|
||||
[json| { address: "zzz" } |]
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 4 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 4 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [ matchContentTypeSingular
|
||||
, "Preference-Applied" <:> "tx=commit" ]
|
||||
@@ -100,7 +100,7 @@ spec =
|
||||
request methodPatch "/items?id=gt.0&id=lt.0"
|
||||
[singular] [json|{"id":1}|]
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [matchContentTypeSingular]
|
||||
}
|
||||
@@ -109,7 +109,7 @@ spec =
|
||||
request methodPatch "/items?id=gt.0&id=lt.0"
|
||||
[("Prefer", "return=representation"), singular] [json|{"id":1}|]
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [matchContentTypeSingular]
|
||||
}
|
||||
@@ -141,7 +141,7 @@ spec =
|
||||
[("Prefer", "tx=commit"), singular]
|
||||
[json| [ { id: 200, address: "xxx" }, { id: 201, address: "yyy" } ] |]
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 2 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 2 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [ matchContentTypeSingular
|
||||
, "Preference-Applied" <:> "tx=commit" ]
|
||||
@@ -157,7 +157,7 @@ spec =
|
||||
[("Prefer", "tx=commit"), ("Prefer", "return=representation"), singular]
|
||||
[json| [ { id: 202, address: "xxx" }, { id: 203, address: "yyy" } ] |]
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 2 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 2 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [ matchContentTypeSingular
|
||||
, "Preference-Applied" <:> "tx=commit" ]
|
||||
@@ -173,7 +173,7 @@ spec =
|
||||
[("Prefer", "tx=commit"), ("Prefer", "return=minimal"), singular]
|
||||
[json| [ { id: 204, address: "xxx" }, { id: 205, address: "yyy" } ] |]
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 2 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 2 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [ matchContentTypeSingular
|
||||
, "Preference-Applied" <:> "tx=commit" ]
|
||||
@@ -189,7 +189,7 @@ spec =
|
||||
[singular]
|
||||
[json| [ ] |]
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [matchContentTypeSingular]
|
||||
}
|
||||
@@ -199,7 +199,7 @@ spec =
|
||||
[("Prefer", "return=representation"), singular]
|
||||
[json| [ ] |]
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [matchContentTypeSingular]
|
||||
}
|
||||
@@ -222,7 +222,7 @@ spec =
|
||||
[("Prefer", "tx=commit"), singular]
|
||||
""
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 5 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 5 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [ matchContentTypeSingular
|
||||
, "Preference-Applied" <:> "tx=commit" ]
|
||||
@@ -240,7 +240,7 @@ spec =
|
||||
request methodDelete "/items?id=gt.5&id=lt.11"
|
||||
[("Prefer", "tx=commit"), ("Prefer", "return=representation"), singular] ""
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 5 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 5 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [ matchContentTypeSingular
|
||||
, "Preference-Applied" <:> "tx=commit" ]
|
||||
@@ -257,7 +257,7 @@ spec =
|
||||
request methodDelete "/items?id=lt.0"
|
||||
[singular] ""
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [matchContentTypeSingular]
|
||||
}
|
||||
@@ -266,7 +266,7 @@ spec =
|
||||
request methodDelete "/items?id=lt.0"
|
||||
[("Prefer", "return=representation"), singular] ""
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [matchContentTypeSingular]
|
||||
}
|
||||
@@ -276,7 +276,7 @@ spec =
|
||||
request methodPost "/rpc/getproject"
|
||||
[singular] [json|{ "id": 9999999}|]
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [matchContentTypeSingular]
|
||||
}
|
||||
@@ -299,7 +299,7 @@ spec =
|
||||
request methodPost "/rpc/getallprojects"
|
||||
[singular] "{}"
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 5 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 5 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [matchContentTypeSingular]
|
||||
}
|
||||
@@ -314,7 +314,7 @@ spec =
|
||||
[("Prefer", "tx=commit"), singular]
|
||||
[json| {"id_l": 1, "id_h": 2, "name": "changed"} |]
|
||||
`shouldRespondWith`
|
||||
[json|{"details":"Results contain 2 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned"}|]
|
||||
[json|{"details":"Results contain 2 rows, application/vnd.pgrst.object+json requires 1 row","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST505","hint":null}|]
|
||||
{ matchStatus = 406
|
||||
, matchHeaders = [ matchContentTypeSingular
|
||||
, "Preference-Applied" <:> "tx=commit" ]
|
||||
|
||||
@@ -33,7 +33,7 @@ spec = do
|
||||
it "fails with 400 and error" $
|
||||
request methodPatch "/simple_pk" [] "}{ x = 2"
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Error in $: Failed reading: not a valid json value at '}{x=2'"}|]
|
||||
[json|{"message":"Error in $: Failed reading: not a valid json value at '}{x=2'","code":"PGRST102","details":null,"hint":null}|]
|
||||
{ matchStatus = 400,
|
||||
matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
@@ -42,7 +42,7 @@ spec = do
|
||||
it "fails with 400 and error" $
|
||||
request methodPatch "/items" [] ""
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Error in $: not enough input"}|]
|
||||
[json|{"message":"Error in $: not enough input","code":"PGRST102","details":null,"hint":null}|]
|
||||
{ matchStatus = 400,
|
||||
matchHeaders = [matchContentTypeJson]
|
||||
}
|
||||
|
||||
@@ -199,73 +199,73 @@ spec actualPgVersion =
|
||||
request methodPut "/tiobe_pls?name=eq.Javascript" [("Range", "0-5")]
|
||||
[json| [ { "name": "Javascript", "rank": 1 } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Range header and limit/offset querystring parameters are not allowed for PUT"}|]
|
||||
[json|{"message":"Range header and limit/offset querystring parameters are not allowed for PUT","code":"PGRST503","details":null,"hint":null}|]
|
||||
{ matchStatus = 400 , matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "fails if limit is specified" $
|
||||
put "/tiobe_pls?name=eq.Javascript&limit=1"
|
||||
[json| [ { "name": "Javascript", "rank": 1 } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Range header and limit/offset querystring parameters are not allowed for PUT"}|]
|
||||
[json|{"message":"Range header and limit/offset querystring parameters are not allowed for PUT","code":"PGRST503","details":null,"hint":null}|]
|
||||
{ matchStatus = 400 , matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "fails if offset is specified" $
|
||||
put "/tiobe_pls?name=eq.Javascript&offset=1"
|
||||
[json| [ { "name": "Javascript", "rank": 1 } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Range header and limit/offset querystring parameters are not allowed for PUT"}|]
|
||||
[json|{"message":"Range header and limit/offset querystring parameters are not allowed for PUT","code":"PGRST503","details":null,"hint":null}|]
|
||||
{ matchStatus = 400 , matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "rejects every other filter than pk cols eq's" $ do
|
||||
put "/tiobe_pls?rank=eq.19"
|
||||
[json| [ { "name": "Go", "rank": 19 } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators"}|]
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators","code":"PGRST105","details":null,"hint":null}|]
|
||||
{ matchStatus = 405 , matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
put "/tiobe_pls?id=not.eq.Java"
|
||||
[json| [ { "name": "Go", "rank": 19 } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators"}|]
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators","code":"PGRST105","details":null,"hint":null}|]
|
||||
{ matchStatus = 405 , matchHeaders = [matchContentTypeJson] }
|
||||
put "/tiobe_pls?id=in.(Go)"
|
||||
[json| [ { "name": "Go", "rank": 19 } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators"}|]
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators","code":"PGRST105","details":null,"hint":null}|]
|
||||
{ matchStatus = 405 , matchHeaders = [matchContentTypeJson] }
|
||||
put "/tiobe_pls?and=(id.eq.Go)"
|
||||
[json| [ { "name": "Go", "rank": 19 } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators"}|]
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators","code":"PGRST105","details":null,"hint":null}|]
|
||||
{ matchStatus = 405 , matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "fails if not all composite key cols are specified as eq filters" $ do
|
||||
put "/employees?first_name=eq.Susan"
|
||||
[json| [ { "first_name": "Susan", "last_name": "Heidt", "salary": "48000", "company": "GEX", "occupation": "Railroad engineer" } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators"}|]
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators","code":"PGRST105","details":null,"hint":null}|]
|
||||
{ matchStatus = 405 , matchHeaders = [matchContentTypeJson] }
|
||||
put "/employees?last_name=eq.Heidt"
|
||||
[json| [ { "first_name": "Susan", "last_name": "Heidt", "salary": "48000", "company": "GEX", "occupation": "Railroad engineer" } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators"}|]
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators","code":"PGRST105","details":null,"hint":null}|]
|
||||
{ matchStatus = 405 , matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "fails if the uri primary key doesn't match the payload primary key" $ do
|
||||
put "/tiobe_pls?name=eq.MATLAB" [json| [ { "name": "Perl", "rank": 17 } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Payload values do not match URL in primary key column(s)"}|]
|
||||
[json|{"message":"Payload values do not match URL in primary key column(s)","code":"PGRST504","details":null,"hint":null}|]
|
||||
{ matchStatus = 400 , matchHeaders = [matchContentTypeJson] }
|
||||
put "/employees?first_name=eq.Wendy&last_name=eq.Anderson"
|
||||
[json| [ { "first_name": "Susan", "last_name": "Heidt", "salary": "48000", "company": "GEX", "occupation": "Railroad engineer" } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Payload values do not match URL in primary key column(s)"}|]
|
||||
[json|{"message":"Payload values do not match URL in primary key column(s)","code":"PGRST504","details":null,"hint":null}|]
|
||||
{ matchStatus = 400 , matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "fails if the table has no PK" $
|
||||
put "/no_pk?a=eq.one&b=eq.two" [json| [ { "a": "one", "b": "two" } ]|]
|
||||
`shouldRespondWith`
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators"}|]
|
||||
[json|{"message":"Filters must include all and only primary key columns with 'eq' operators","code":"PGRST105","details":null,"hint":null}|]
|
||||
{ matchStatus = 405 , matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
context "Inserting row" $ do
|
||||
|
||||
Reference in New Issue
Block a user