Skip to content

Commit

Permalink
Add hint to verify table and foreign key existence on a relationship …
Browse files Browse the repository at this point in the history
…error
  • Loading branch information
laurenceisla authored Dec 20, 2021
1 parent cc8a7ef commit c858d15
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 23 deletions.
2 changes: 1 addition & 1 deletion postgrest.cabal
Original file line number Diff line number Diff line change
@@ -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
Expand Down
10 changes: 5 additions & 5 deletions src/PostgREST/Error.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion src/PostgREST/Request/DbRequestBuilder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions test/Feature/EmbedDisambiguationSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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] }

Expand Down Expand Up @@ -425,16 +425,16 @@ 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" $
-- ensures the "invalid reference to FROM-clause entry for table "rollen" error doesn't happen.
-- 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] }
20 changes: 10 additions & 10 deletions test/Feature/QuerySpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
}
Expand Down Expand Up @@ -489,35 +489,35 @@ 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]
}

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]
}

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]
}

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]
}
Expand Down

0 comments on commit c858d15

Please sign in to comment.