diff --git a/postgrest.cabal b/postgrest.cabal index 871630cb00..c8bbf98bff 100644 --- a/postgrest.cabal +++ b/postgrest.cabal @@ -1,5 +1,5 @@ name: postgrest -version: 9.0.0 +version: 9.0.0.20211220 synopsis: REST API for any Postgres database description: Reads the schema of a PostgreSQL database and creates RESTful routes for the tables and views, supporting all HTTP verbs that security diff --git a/src/PostgREST/Error.hs b/src/PostgREST/Error.hs index bf676eb715..c3fc8c3a81 100644 --- a/src/PostgREST/Error.hs +++ b/src/PostgREST/Error.hs @@ -59,7 +59,7 @@ data ApiRequestError | InvalidRange | InvalidBody ByteString | ParseRequestError Text Text - | NoRelBetween Text Text + | NoRelBetween Text Text Text | AmbiguousRelBetween Text Text [Relationship] | AmbiguousRpc [ProcDescription] | NoRpc Text Text [Text] Bool ContentType Bool @@ -75,7 +75,7 @@ instance PgrstError ApiRequestError where status UnsupportedVerb = HTTP.status405 status ActionInappropriate = HTTP.status405 status (ParseRequestError _ _) = HTTP.status400 - status (NoRelBetween _ _) = HTTP.status400 + status NoRelBetween{} = HTTP.status400 status AmbiguousRelBetween{} = HTTP.status300 status (AmbiguousRpc _) = HTTP.status300 status NoRpc{} = HTTP.status404 @@ -93,9 +93,9 @@ instance JSON.ToJSON ApiRequestError where "message" .= T.decodeUtf8 errorMessage] toJSON InvalidRange = JSON.object [ "message" .= ("HTTP Range error" :: Text)] - toJSON (NoRelBetween parent child) = JSON.object [ - "hint" .= ("If a new foreign key between these entities was created in the database, try reloading the schema cache." :: Text), - "message" .= ("Could not find a relationship between " <> parent <> " and " <> child <> " in the schema cache" :: Text)] + toJSON (NoRelBetween parent child schema) = JSON.object [ + "hint" .= ("Verify that '" <> parent <> "' and '" <> child <> "' exist in the schema '" <> schema <> "' and that there is a foreign key relationship between them. If a new relationship was created, try reloading the schema cache." :: Text), + "message" .= ("Could not find a relationship between '" <> parent <> "' and '" <> child <> "' in the schema cache" :: Text)] toJSON (AmbiguousRelBetween parent child rels) = JSON.object [ "hint" .= ("Try changing '" <> child <> "' to one of the following: " <> relHint rels <> ". Find the desired relationship in the 'details' key." :: Text), "message" .= ("Could not embed because more than one relationship was found for '" <> parent <> "' and '" <> child <> "'" :: Text), diff --git a/src/PostgREST/Request/DbRequestBuilder.hs b/src/PostgREST/Request/DbRequestBuilder.hs index 35af9962d4..0face26953 100644 --- a/src/PostgREST/Request/DbRequestBuilder.hs +++ b/src/PostgREST/Request/DbRequestBuilder.hs @@ -153,7 +153,7 @@ addRels schema allRels parentNode (Node (query@Select{from=tbl}, (nodeName, _, a findRel :: Schema -> [Relationship] -> NodeName -> NodeName -> Maybe Hint -> Either ApiRequestError Relationship findRel schema allRels origin target hint = case rel of - [] -> Left $ NoRelBetween origin target + [] -> Left $ NoRelBetween origin target schema [r] -> Right r -- Here we handle a self reference relationship to not cause a breaking -- change: In a self reference we get two relationships with the same diff --git a/test/Feature/EmbedDisambiguationSpec.hs b/test/Feature/EmbedDisambiguationSpec.hs index 44bfa608f0..5e21188f3d 100644 --- a/test/Feature/EmbedDisambiguationSpec.hs +++ b/test/Feature/EmbedDisambiguationSpec.hs @@ -174,8 +174,8 @@ spec = it "fails if the fk is not known" $ get "/message?select=id,sender:person!space(name)&id=lt.4" `shouldRespondWith` [json|{ - "hint":"If a new foreign key between these entities was created in the database, try reloading the schema cache.", - "message":"Could not find a relationship between message and person in the schema cache"}|] + "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"}|] { matchStatus = 400 , matchHeaders = [matchContentTypeJson] } @@ -425,8 +425,8 @@ spec = it "doesn't work if the junction is only internal" $ get "/end_1?select=end_2(*)" `shouldRespondWith` [json|{ - "hint":"If a new foreign key between these entities was created in the database, try reloading the schema cache.", - "message":"Could not find a relationship between end_1 and end_2 in the schema cache"}|] + "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"}|] { matchStatus = 400 , matchHeaders = [matchContentTypeJson] } it "shouldn't try to embed if the private junction has an exposed homonym" $ @@ -434,7 +434,7 @@ spec = -- Ref: https://github.com/PostgREST/postgrest/issues/1587#issuecomment-734995669 get "/schauspieler?select=filme(*)" `shouldRespondWith` [json|{ - "hint":"If a new foreign key between these entities was created in the database, try reloading the schema cache.", - "message":"Could not find a relationship between schauspieler and filme in the schema cache"}|] + "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"}|] { matchStatus = 400 , matchHeaders = [matchContentTypeJson] } diff --git a/test/Feature/QuerySpec.hs b/test/Feature/QuerySpec.hs index 23e077f663..10250204cd 100644 --- a/test/Feature/QuerySpec.hs +++ b/test/Feature/QuerySpec.hs @@ -260,8 +260,8 @@ spec actualPgVersion = do it "matches filtering nested items 2" $ get "/clients?select=id,projects(id,tasks2(id,name))&projects.tasks.name=like.Design*" `shouldRespondWith` [json| { - "hint":"If a new foreign key between these entities was created in the database, try reloading the schema cache.", - "message":"Could not find a relationship between projects and tasks2 in the schema cache"}|] + "hint":"Verify that 'projects' and 'tasks2' 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 'projects' and 'tasks2' in the schema cache"}|] { matchStatus = 400 , matchHeaders = [matchContentTypeJson] } @@ -489,8 +489,8 @@ spec actualPgVersion = do it "cannot request partitions as children from a partitioned table" $ get "/car_models?id=in.(1,2,4)&select=id,name,car_model_sales_202101(id)&order=id.asc" `shouldRespondWith` [json| - {"hint":"If a new foreign key between these entities was created in the database, try reloading the schema cache.", - "message":"Could not find a relationship between car_models and car_model_sales_202101 in the schema cache"} |] + {"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.", + "message":"Could not find a relationship between 'car_models' and 'car_model_sales_202101' in the schema cache"} |] { matchStatus = 400 , matchHeaders = [matchContentTypeJson] } @@ -498,8 +498,8 @@ spec actualPgVersion = do it "cannot request a partitioned table as parent from a partition" $ get "/car_model_sales_202101?select=id,name,car_models(id,name)&order=id.asc" `shouldRespondWith` [json| - {"hint":"If a new foreign key between these entities was created in the database, try reloading the schema cache.", - "message":"Could not find a relationship between car_model_sales_202101 and car_models in the schema cache"} |] + {"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.", + "message":"Could not find a relationship between 'car_model_sales_202101' and 'car_models' in the schema cache"} |] { matchStatus = 400 , matchHeaders = [matchContentTypeJson] } @@ -507,8 +507,8 @@ spec actualPgVersion = do it "cannot request a partition as parent from a partitioned table" $ get "/car_model_sales?id=in.(1,3,4)&select=id,name,car_models_default(id,name)&order=id.asc" `shouldRespondWith` [json| - {"hint":"If a new foreign key between these entities was created in the database, try reloading the schema cache.", - "message":"Could not find a relationship between car_model_sales and car_models_default in the schema cache"} |] + {"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.", + "message":"Could not find a relationship between 'car_model_sales' and 'car_models_default' in the schema cache"} |] { matchStatus = 400 , matchHeaders = [matchContentTypeJson] } @@ -516,8 +516,8 @@ spec actualPgVersion = do it "cannot request partitioned tables as children from a partition" $ get "/car_models_default?select=id,name,car_model_sales(id,name)&order=id.asc" `shouldRespondWith` [json| - {"hint":"If a new foreign key between these entities was created in the database, try reloading the schema cache.", - "message":"Could not find a relationship between car_models_default and car_model_sales in the schema cache"} |] + {"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.", + "message":"Could not find a relationship between 'car_models_default' and 'car_model_sales' in the schema cache"} |] { matchStatus = 400 , matchHeaders = [matchContentTypeJson] }