diff --git a/src/PostgREST/Error.hs b/src/PostgREST/Error.hs index ac2debbff1..ebb8a7caaf 100644 --- a/src/PostgREST/Error.hs +++ b/src/PostgREST/Error.hs @@ -180,22 +180,25 @@ instance JSON.ToJSON ApiRequestError where "hint" .= ("Try changing '" <> child <> "' to one of the following: " <> relHint rels <> ". Find the desired relationship in the 'details' key." :: Text)] toJSON (NoRpc schema procName argumentKeys hasPreferSingleObject contentType isInvPost allProcs overloadedProcs) = let func = schema <> "." <> procName - prms = "(" <> T.intercalate ", " argumentKeys <> ")" - fmtParams = if null argumentKeys then " function without parameters" else prms <> " function" + prms = T.intercalate ", " argumentKeys + prmsMsg = "(" <> prms <> ")" + prmsDet = " with parameter" <> (if length argumentKeys > 1 then "s " else " ") <> prms + fmtPrms p = if null argumentKeys then " without parameters" else p + onlySingleParams = hasPreferSingleObject || (isInvPost && contentType `elem` [MTTextPlain, MTTextXML, MTOctetStream]) in JSON.object [ "code" .= SchemaCacheErrorCode02, - "message" .= ("Could not find the " <> func <> + "message" .= ("Could not find the function " <> func <> (if onlySingleParams then "" else fmtPrms prmsMsg) <> " in the schema cache"), + "details" .= ("Searched for the function " <> func <> (case (hasPreferSingleObject, isInvPost, contentType) of - (True, _, _) -> " function with a single json or jsonb parameter" - (_, True, MTTextPlain) -> " function with a single unnamed text parameter" - (_, True, MTTextXML) -> " function with a single unnamed xml parameter" - (_, True, MTOctetStream) -> " function with a single unnamed bytea parameter" - (_, True, MTApplicationJSON) -> fmtParams <> " or the " <> func <>" function with a single unnamed json or jsonb parameter" - _ -> fmtParams) <> - " in the schema cache"), - "details" .= JSON.Null, + (True, _, _) -> " with a single json/jsonb parameter" + (_, True, MTTextPlain) -> " with a single unnamed text parameter" + (_, True, MTTextXML) -> " with a single unnamed xml parameter" + (_, True, MTOctetStream) -> " with a single unnamed bytea parameter" + (_, True, MTApplicationJSON) -> fmtPrms prmsDet <> " or with a single unnamed json/jsonb parameter" + _ -> fmtPrms prmsDet) <> + ", but no matches were found in the schema cache."), -- The hint will be null in the case of single unnamed parameter functions - "hint" .= if hasPreferSingleObject || (isInvPost && contentType `elem` [MTTextPlain, MTTextXML, MTOctetStream]) + "hint" .= if onlySingleParams then Nothing else noRpcHint schema procName argumentKeys allProcs overloadedProcs ] toJSON (AmbiguousRpc procs) = JSON.object [ diff --git a/test/spec/Feature/Query/RpcSpec.hs b/test/spec/Feature/Query/RpcSpec.hs index b8dfa5ba71..f9275f6625 100644 --- a/test/spec/Feature/Query/RpcSpec.hs +++ b/test/spec/Feature/Query/RpcSpec.hs @@ -124,9 +124,9 @@ spec actualPgVersion = get "/rpc/sayhell" `shouldRespondWith` [json| { "hint":"Perhaps you meant to call the function test.sayhello", - "message":"Could not find the test.sayhell function without parameters in the schema cache", + "message":"Could not find the function test.sayhell without parameters in the schema cache", "code":"PGRST202", - "details":null} |] + "details":"Searched for the function test.sayhell without parameters, but no matches were found in the schema cache."} |] { matchStatus = 404 , matchHeaders = [matchContentTypeJson] } @@ -139,9 +139,9 @@ spec actualPgVersion = get "/rpc/sayhello?nam=Peter" `shouldRespondWith` [json| { "hint":"Perhaps you meant to call the function test.sayhello(name)", - "message":"Could not find the test.sayhello(nam) function in the schema cache", + "message":"Could not find the function test.sayhello(nam) in the schema cache", "code":"PGRST202", - "details":null} |] + "details":"Searched for the function test.sayhello with parameter nam, but no matches were found in the schema cache."} |] { matchStatus = 404 , matchHeaders = [matchContentTypeJson] } @@ -150,9 +150,9 @@ spec actualPgVersion = get "/rpc/add_them?a=1&b=2&smthelse=blabla" `shouldRespondWith` [json| { "hint":"Perhaps you meant to call the function test.add_them(a, b)", - "message":"Could not find the test.add_them(a, b, smthelse) function in the schema cache", + "message":"Could not find the function test.add_them(a, b, smthelse) in the schema cache", "code":"PGRST202", - "details":null} |] + "details":"Searched for the function test.add_them with parameters a, b, smthelse, but no matches were found in the schema cache."} |] { matchStatus = 404 , matchHeaders = [matchContentTypeJson] } @@ -164,9 +164,9 @@ spec actualPgVersion = `shouldRespondWith` [json| { "hint":null, - "message":"Could not find the test.sayhello function with a single json or jsonb parameter in the schema cache", + "message":"Could not find the function test.sayhello in the schema cache", "code":"PGRST202", - "details":null} |] + "details":"Searched for the function test.sayhello with a single json/jsonb parameter, but no matches were found in the schema cache."} |] { matchStatus = 404 , matchHeaders = [matchContentTypeJson] } @@ -175,18 +175,18 @@ spec actualPgVersion = get "/rpc/overloaded?wrong_arg=value" `shouldRespondWith` [json| { "hint":null, - "message":"Could not find the test.overloaded(wrong_arg) function in the schema cache", + "message":"Could not find the function test.overloaded(wrong_arg) in the schema cache", "code":"PGRST202", - "details":null} |] + "details":"Searched for the function test.overloaded with parameter wrong_arg, but no matches were found in the schema cache."} |] { matchStatus = 404 , matchHeaders = [matchContentTypeJson] } get "/rpc/overloaded?a=1&b=2&wrong_arg=value" `shouldRespondWith` [json| { "hint":"Perhaps you meant to call the function test.overloaded(a, b, c)", - "message":"Could not find the test.overloaded(a, b, wrong_arg) function in the schema cache", + "message":"Could not find the function test.overloaded(a, b, wrong_arg) in the schema cache", "code":"PGRST202", - "details":null} |] + "details":"Searched for the function test.overloaded with parameters a, b, wrong_arg, but no matches were found in the schema cache."} |] { matchStatus = 404 , matchHeaders = [matchContentTypeJson] } @@ -1274,9 +1274,9 @@ spec actualPgVersion = `shouldRespondWith` [json|{ "hint": "Perhaps you meant to call the function test.unnamed_text_param", - "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 function test.unnamed_int_param(x, y) in the schema cache", "code":"PGRST202", - "details":null + "details":"Searched for the function test.unnamed_int_param with parameters x, y or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache." }|] { matchStatus = 404 , matchHeaders = [ matchContentTypeJson ] @@ -1289,9 +1289,9 @@ spec actualPgVersion = `shouldRespondWith` [json|{ "hint": null, - "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 function test.unnamed_int_param in the schema cache", "code":"PGRST202", - "details":null + "details":"Searched for the function test.unnamed_int_param with a single unnamed text parameter, but no matches were found in the schema cache." }|] { matchStatus = 404 , matchHeaders = [ matchContentTypeJson ] @@ -1304,9 +1304,9 @@ spec actualPgVersion = `shouldRespondWith` [json|{ "hint": null, - "message": "Could not find the test.unnamed_int_param function with a single unnamed xml parameter in the schema cache", + "message": "Could not find the function test.unnamed_int_param in the schema cache", "code":"PGRST202", - "details":null + "details":"Searched for the function test.unnamed_int_param with a single unnamed xml parameter, but no matches were found in the schema cache." }|] { matchStatus = 404 , matchHeaders = [ matchContentTypeJson ] @@ -1320,9 +1320,9 @@ spec actualPgVersion = `shouldRespondWith` [json|{ "hint": null, - "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 function test.unnamed_int_param in the schema cache", "code":"PGRST202", - "details":null + "details":"Searched for the function test.unnamed_int_param with a single unnamed bytea parameter, but no matches were found in the schema cache." }|] { matchStatus = 404 , matchHeaders = [ matchContentTypeJson ] @@ -1380,9 +1380,9 @@ spec actualPgVersion = `shouldRespondWith` [json| { "hint":"Perhaps you meant to call the function test.overloaded_unnamed_param(x, y)", - "message":"Could not find the test.overloaded_unnamed_param(a, b) function in the schema cache", + "message":"Could not find the function test.overloaded_unnamed_param(a, b) in the schema cache", "code":"PGRST202", - "details":null + "details":"Searched for the function test.overloaded_unnamed_param with parameters a, b, but no matches were found in the schema cache." }|] { matchStatus = 404 , matchHeaders = [matchContentTypeJson]