diff --git a/src/PostgREST/Plan.hs b/src/PostgREST/Plan.hs index fea81c2b3c..50573e3b3d 100644 --- a/src/PostgREST/Plan.hs +++ b/src/PostgREST/Plan.hs @@ -968,7 +968,7 @@ updateNode f (targetNodeName:remainingPath, a) (Right (Node rootNode forest)) = updateNode f (remainingPath, a) (Right target) where findNode :: Maybe ReadPlanTree - findNode = find (\(Node ReadPlan{relName, relAlias} _) -> relName == targetNodeName || relAlias == Just targetNodeName) forest + findNode = find (\(Node ReadPlan{relName, relAlias} _) -> fromMaybe relName relAlias == targetNodeName) forest mutatePlan :: Mutation -> QualifiedIdentifier -> ApiRequest -> SchemaCache -> ReadPlanTree -> Either Error MutatePlan mutatePlan mutation qi ApiRequest{iPreferences=Preferences{..}, ..} SchemaCache{dbTables, dbRepresentations} readReq = diff --git a/test/spec/Feature/Query/QuerySpec.hs b/test/spec/Feature/Query/QuerySpec.hs index 43cb46723d..92bb73a23d 100644 --- a/test/spec/Feature/Query/QuerySpec.hs +++ b/test/spec/Feature/Query/QuerySpec.hs @@ -1056,6 +1056,16 @@ spec = do { "id":4,"children":[]} ]|] { matchHeaders = [matchContentTypeJson] } + it "works when embedding the same table more than once" $ + get "/places?select=name,visits(id,start_time,visit_type),work_visits:visits(id,start_time,visit_type)&id=eq.1&visits.visit_type=neq.work&visits.start_time=gt.20250101+00:00&work_visits.visit_type=eq.work&work_visits.start_time=gt.20250101+00:00" `shouldRespondWith` + [json|[ + { + "name":"Lake", + "visits":[{"id": 1, "start_time": "2025-01-01T10:00:00", "visit_type": "vacation"}, {"id": 2, "start_time": "2025-01-01T15:00:00", "visit_type": "vacation"}], + "work_visits":[{"id": 3, "start_time": "2025-01-01T20:00:00", "visit_type": "work"}] + } + ]|] { matchHeaders = [matchContentTypeJson] } + describe "ordering response" $ do it "by a column asc" $ get "/items?id=lte.2&order=id.asc" @@ -1138,7 +1148,7 @@ spec = do { matchHeaders = [matchContentTypeJson] } it "ordering embeded entities with alias" $ - get "/projects?id=eq.1&select=id, name, the_tasks:tasks(id, name)&tasks.order=name.asc" `shouldRespondWith` + get "/projects?id=eq.1&select=id, name, the_tasks:tasks(id, name)&the_tasks.order=name.asc" `shouldRespondWith` [json|[{"id":1,"name":"Windows 7","the_tasks":[{"id":2,"name":"Code w7"},{"id":1,"name":"Design w7"}]}]|] { matchHeaders = [matchContentTypeJson] } diff --git a/test/spec/fixtures/data.sql b/test/spec/fixtures/data.sql index ad9c678a7b..f8ed5f8d10 100644 --- a/test/spec/fixtures/data.sql +++ b/test/spec/fixtures/data.sql @@ -961,8 +961,21 @@ INSERT INTO artists VALUES (1, 'duster'), (2, 'black country, new road'), (3, 'bjork'); TRUNCATE TABLE albums CASCADE; -INSERT INTO albums +INSERT INTO albums VALUES (1, 'stratosphere', 1), - (2, 'ants from up above',2), + (2, 'ants from up above',2), (3, 'vespertine',3), (4, 'contemporary movement', 1); + +TRUNCATE TABLE places CASCADE; +INSERT INTO places (name) +VALUES ('Lake'), ('Mountain'), ('Beach'); + +TRUNCATE TABLE visits CASCADE; +INSERT INTO visits (place_id, start_time, end_time, visit_type) +VALUES (1, '2025-01-01 10:00','2025-01-01 11:00', 'vacation'), + (1, '2025-01-01 15:00','2025-01-01 16:00', 'vacation'), + (1, '2025-01-01 20:00', '2025-01-01 21:00', 'work'), + (2, '2024-11-01 09:00','2024-11-01 10:00', 'vacation'), + (3, '2024-12-02 13:00','2024-12-02 14:00', 'vacation'), + (1, '2023-01-02 20:00','2023-01-01 21:00', 'work'); diff --git a/test/spec/fixtures/schema.sql b/test/spec/fixtures/schema.sql index 42c25dcb16..542d71fbfc 100644 --- a/test/spec/fixtures/schema.sql +++ b/test/spec/fixtures/schema.sql @@ -3820,3 +3820,18 @@ comment on function test.collision_test_func(id integer) is 'fizzbuzz'; create or replace function test.delete_all_items() returns setof items as $$ delete from items where id <= 15 returning *; -- deletes 15 items, then return them $$ language sql; + +create type visit_type as enum ('vacation', 'work'); + +create table places ( + id int primary key generated always as identity, + name text not null +); + +create table visits ( + id int primary key generated always as identity, + place_id int not null references places(id), + start_time timestamp, + end_time timestamp, + visit_type visit_type +);