Skip to content

Commit

Permalink
correct spread embed to '...'
Browse files Browse the repository at this point in the history
  • Loading branch information
steve-chavez committed Dec 6, 2022
1 parent 9e56721 commit a5465e2
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 24 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- #1414, Add related orders - @steve-chavez
+ On a many-to-one or one-to-one relationship, you can order a parent by a child column `/projects?select=*,clients(*)&order=clients(name).desc.nullsfirst`
- #1233, #1907, #2566, Allow spreading embedded resources - @steve-chavez
+ On a many-to-one or one-to-one relationship, you can unnest a json object with `/projects?select=*,..clients(client_name:name)`
+ On a many-to-one or one-to-one relationship, you can unnest a json object with `/projects?select=*,...clients(client_name:name)`
+ Allows including the join table columns when resource embedding
+ Allows disambiguating a recursive m2m embed
+ Allows disambiguating an embed that has a many-to-many relationship using two foreign keys on a junction
Expand Down
16 changes: 8 additions & 8 deletions src/PostgREST/ApiRequest/QueryParams.hs
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ pTreePath = do
-- >>> P.parse pFieldForest "" "*,client(*,nested(*))"
-- Right [Node {rootLabel = SelectField {selField = ("*",[]), selCast = Nothing, selAlias = Nothing}, subForest = []},Node {rootLabel = SelectRelation {selRelation = "client", selAlias = Nothing, selHint = Nothing, selJoinType = Nothing}, subForest = [Node {rootLabel = SelectField {selField = ("*",[]), selCast = Nothing, selAlias = Nothing}, subForest = []},Node {rootLabel = SelectRelation {selRelation = "nested", selAlias = Nothing, selHint = Nothing, selJoinType = Nothing}, subForest = [Node {rootLabel = SelectField {selField = ("*",[]), selCast = Nothing, selAlias = Nothing}, subForest = []}]}]}]
--
-- >>> P.parse pFieldForest "" "*,..client(*),other(*)"
-- >>> P.parse pFieldForest "" "*,...client(*),other(*)"
-- Right [Node {rootLabel = SelectField {selField = ("*",[]), selCast = Nothing, selAlias = Nothing}, subForest = []},Node {rootLabel = SpreadRelation {selRelation = "client", selHint = Nothing, selJoinType = Nothing}, subForest = [Node {rootLabel = SelectField {selField = ("*",[]), selCast = Nothing, selAlias = Nothing}, subForest = []}]},Node {rootLabel = SelectRelation {selRelation = "other", selAlias = Nothing, selHint = Nothing, selJoinType = Nothing}, subForest = [Node {rootLabel = SelectField {selField = ("*",[]), selCast = Nothing, selAlias = Nothing}, subForest = []}]}]
--
-- >>> P.parse pFieldForest "" ""
Expand Down Expand Up @@ -542,28 +542,28 @@ pFieldSelect = lexeme $ try (do
-- |
-- Parse spread relations in select
--
-- >>> P.parse pSpreadRelationSelect "" "..rel(*)"
-- >>> P.parse pSpreadRelationSelect "" "...rel(*)"
-- Right (SpreadRelation {selRelation = "rel", selHint = Nothing, selJoinType = Nothing})
--
-- >>> P.parse pSpreadRelationSelect "" "..rel!hint!inner(*)"
-- >>> P.parse pSpreadRelationSelect "" "...rel!hint!inner(*)"
-- Right (SpreadRelation {selRelation = "rel", selHint = Just "hint", selJoinType = Just JTInner})
--
-- >>> P.parse pSpreadRelationSelect "" "rel(*)"
-- Left (line 1, column 1):
-- unexpected "r"
-- expecting "..."
--
-- >>> P.parse pSpreadRelationSelect "" "alias:..rel(*)"
-- >>> P.parse pSpreadRelationSelect "" "alias:...rel(*)"
-- Left (line 1, column 1):
-- unexpected "a"
-- expecting ".."
-- expecting "..."
--
-- >>> P.parse pSpreadRelationSelect "" "..rel->jsonpath(*)"
-- Left (line 1, column 8):
-- >>> P.parse pSpreadRelationSelect "" "...rel->jsonpath(*)"
-- Left (line 1, column 9):
-- unexpected '>'
pSpreadRelationSelect :: Parser SelectItem
pSpreadRelationSelect = lexeme $ do
name <- string ".." >> pFieldName
name <- string "..." >> pFieldName
(hint, jType) <- pEmbedParams
try (void $ lookAhead (string "("))
return $ SpreadRelation name hint jType
Expand Down
12 changes: 6 additions & 6 deletions test/spec/Feature/Query/EmbedDisambiguationSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,18 @@ spec =
, matchHeaders = [matchContentTypeJson]
}
-- Each of those 4 possibilities can be done with spread embeds, by following the details in the error above
get "/whatev_sites?select=*,whatev_jobs!site_id_1(..whatev_projects!project_id_1(*))" `shouldRespondWith` [json|[]|]
get "/whatev_sites?select=*,whatev_jobs!site_id_1(..whatev_projects!project_id_2(*))" `shouldRespondWith` [json|[]|]
get "/whatev_sites?select=*,whatev_jobs!site_id_2(..whatev_projects!project_id_1(*))" `shouldRespondWith` [json|[]|]
get "/whatev_sites?select=*,whatev_jobs!site_id_2(..whatev_projects!project_id_2(*))" `shouldRespondWith` [json|[]|]
get "/whatev_sites?select=*,whatev_jobs!site_id_1(...whatev_projects!project_id_1(*))" `shouldRespondWith` [json|[]|]
get "/whatev_sites?select=*,whatev_jobs!site_id_1(...whatev_projects!project_id_2(*))" `shouldRespondWith` [json|[]|]
get "/whatev_sites?select=*,whatev_jobs!site_id_2(...whatev_projects!project_id_1(*))" `shouldRespondWith` [json|[]|]
get "/whatev_sites?select=*,whatev_jobs!site_id_2(...whatev_projects!project_id_2(*))" `shouldRespondWith` [json|[]|]

it "can disambiguate a recursive m2m with spread embeds" $ do
get "/posters?select=*,subscribers:subscriptions!subscribed(..posters!subscriber(*))&limit=1" `shouldRespondWith`
get "/posters?select=*,subscribers:subscriptions!subscribed(...posters!subscriber(*))&limit=1" `shouldRespondWith`
[json| [ {"id":1,"name":"Mark","subscribers":[{"id":3,"name":"Bill"}, {"id":4,"name":"Jeff"}]}]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
get "/posters?select=*,subscriptions!subscriber(..posters!subscribed(*))&limit=1" `shouldRespondWith`
get "/posters?select=*,subscriptions!subscriber(...posters!subscribed(*))&limit=1" `shouldRespondWith`
[json| [{"id":1,"name":"Mark","subscriptions":[{"id":2,"name":"Elon"}]}]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
Expand Down
18 changes: 9 additions & 9 deletions test/spec/Feature/Query/SpreadQueriesSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ spec :: SpecWith ((), Application)
spec =
describe "spread embeds" $ do
it "works on a many-to-one relationship" $ do
get "/projects?select=id,..clients(client_name:name)" `shouldRespondWith`
get "/projects?select=id,...clients(client_name:name)" `shouldRespondWith`
[json|[
{"id":1,"client_name":"Microsoft"},
{"id":2,"client_name":"Microsoft"},
Expand All @@ -24,7 +24,7 @@ spec =
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
get "/grandchild_entities?select=name,..child_entities(parent_name:name,..entities(grandparent_name:name))&limit=3" `shouldRespondWith`
get "/grandchild_entities?select=name,...child_entities(parent_name:name,...entities(grandparent_name:name))&limit=3" `shouldRespondWith`
[json|[
{"name":"grandchild entity 1","parent_name":"child entity 1","grandparent_name":"entity 1"},
{"name":"grandchild entity 2","parent_name":"child entity 1","grandparent_name":"entity 1"},
Expand All @@ -33,7 +33,7 @@ spec =
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
get "/videogames?select=name,..computed_designers(designer_name:name)" `shouldRespondWith`
get "/videogames?select=name,...computed_designers(designer_name:name)" `shouldRespondWith`
[json|[
{"name":"Civilization I","designer_name":"Sid Meier"},
{"name":"Civilization II","designer_name":"Sid Meier"},
Expand All @@ -45,7 +45,7 @@ spec =
}

it "works inside a normal embed" $
get "/grandchild_entities?select=name,child_entity:child_entities(name,..entities(parent_name:name))&limit=1" `shouldRespondWith`
get "/grandchild_entities?select=name,child_entity:child_entities(name,...entities(parent_name:name))&limit=1" `shouldRespondWith`
[json|[
{"name":"grandchild entity 1","child_entity":{"name":"child entity 1","parent_name":"entity 1"}}
]|]
Expand All @@ -54,7 +54,7 @@ spec =
}

it "works on a one-to-one relationship" $
get "/country?select=name,..capital(capital:name)" `shouldRespondWith`
get "/country?select=name,...capital(capital:name)" `shouldRespondWith`
[json|[
{"name":"Afghanistan","capital":"Kabul"},
{"name":"Algeria","capital":"Algiers"}
Expand All @@ -64,7 +64,7 @@ spec =
}

it "fails when is not a to-one relationship" $ do
get "/clients?select=*,..projects(*)" `shouldRespondWith`
get "/clients?select=*,...projects(*)" `shouldRespondWith`
[json|{
"code":"PGRST119",
"details":"'clients' and 'projects' do not form a many-to-one or one-to-one relationship",
Expand All @@ -74,7 +74,7 @@ spec =
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}
get "/designers?select=*,..computed_videogames(*)" `shouldRespondWith`
get "/designers?select=*,...computed_videogames(*)" `shouldRespondWith`
[json|{
"code":"PGRST119",
"details":"'designers' and 'computed_videogames' do not form a many-to-one or one-to-one relationship",
Expand All @@ -86,7 +86,7 @@ spec =
}

it "can include or exclude attributes of the junction on a m2m" $ do
get "/users?select=*,tasks:users_tasks(*,..tasks(*))&limit=1" `shouldRespondWith`
get "/users?select=*,tasks:users_tasks(*,...tasks(*))&limit=1" `shouldRespondWith`
[json|[{
"id":1,"name":"Angela Martin",
"tasks": [
Expand All @@ -99,7 +99,7 @@ spec =
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
get "/users?select=*,tasks:users_tasks(..tasks(*))&limit=1" `shouldRespondWith`
get "/users?select=*,tasks:users_tasks(...tasks(*))&limit=1" `shouldRespondWith`
[json|[{
"id":1,"name":"Angela Martin",
"tasks":[
Expand Down

0 comments on commit a5465e2

Please sign in to comment.