fix: unexpected results when embedding the same table twice
This commit is contained in:
committed by
Wolfgang Walther
parent
ea08a4d767
commit
5f6f7dca44
@@ -20,6 +20,7 @@ All notable changes to this project will be documented in this file. From versio
|
|||||||
- Shutdown should wait for in flight requests by @mkleczek in #4702
|
- Shutdown should wait for in flight requests by @mkleczek in #4702
|
||||||
- Fix login with uppercase and mixed case role names by @taimoorzaeem in #4678
|
- Fix login with uppercase and mixed case role names by @taimoorzaeem in #4678
|
||||||
- Remove automatic transaction retries on `40001 (serialization_failure)` errors to prevent replication lag by @laurenceisla in #3673
|
- Remove automatic transaction retries on `40001 (serialization_failure)` errors to prevent replication lag by @laurenceisla in #3673
|
||||||
|
- Fix unexpected results when embedding and filtering the same table more than once by @laurenceisla in #4075
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
@@ -29,6 +30,8 @@ All notable changes to this project will be documented in this file. From versio
|
|||||||
+ Now fails at startup. Prior to this, it failed with `PGRST205` on requests related to these schemas.
|
+ Now fails at startup. Prior to this, it failed with `PGRST205` on requests related to these schemas.
|
||||||
- Build a static executable for aarch64-linux by @wolfgangwalther in #4193
|
- Build a static executable for aarch64-linux by @wolfgangwalther in #4193
|
||||||
- Build the minimal docker image for aarch64-linux by @wolfgangwalther in #4193
|
- Build the minimal docker image for aarch64-linux by @wolfgangwalther in #4193
|
||||||
|
- The name of an embedded table can no longer be used in filters if it has an alias by @laurenceisla in #4075
|
||||||
|
+ e.g. `?select=alias:table(*)&table.id=eq.1` is not possible anymore, use `?select=alias:table(*)&alias.id=eq.1` instead.
|
||||||
|
|
||||||
## [14.10] - 2026-04-16
|
## [14.10] - 2026-04-16
|
||||||
|
|
||||||
|
|||||||
@@ -996,7 +996,7 @@ updateNode f (targetNodeName:remainingPath, a) (Right (Node rootNode forest)) =
|
|||||||
updateNode f (remainingPath, a) (Right target)
|
updateNode f (remainingPath, a) (Right target)
|
||||||
where
|
where
|
||||||
findNode :: Maybe ReadPlanTree
|
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 -> QualifiedIdentifier -> ApiRequest -> SchemaCache -> ReadPlanTree -> Either Error MutatePlan
|
||||||
mutatePlan mutation qi ApiRequest{iPreferences=Preferences{..}, ..} SchemaCache{dbTables, dbRepresentations} readReq =
|
mutatePlan mutation qi ApiRequest{iPreferences=Preferences{..}, ..} SchemaCache{dbTables, dbRepresentations} readReq =
|
||||||
|
|||||||
@@ -1070,6 +1070,16 @@ spec = do
|
|||||||
{ "id":4,"children":[]}
|
{ "id":4,"children":[]}
|
||||||
]|] { matchHeaders = [matchContentTypeJson] }
|
]|] { 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
|
describe "ordering response" $ do
|
||||||
it "by a column asc" $
|
it "by a column asc" $
|
||||||
get "/items?id=lte.2&order=id.asc"
|
get "/items?id=lte.2&order=id.asc"
|
||||||
@@ -1152,7 +1162,7 @@ spec = do
|
|||||||
{ matchHeaders = [matchContentTypeJson] }
|
{ matchHeaders = [matchContentTypeJson] }
|
||||||
|
|
||||||
it "ordering embeded entities with alias" $
|
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"}]}]|]
|
[json|[{"id":1,"name":"Windows 7","the_tasks":[{"id":2,"name":"Code w7"},{"id":1,"name":"Design w7"}]}]|]
|
||||||
{ matchHeaders = [matchContentTypeJson] }
|
{ matchHeaders = [matchContentTypeJson] }
|
||||||
|
|
||||||
|
|||||||
Vendored
+13
@@ -970,3 +970,16 @@ VALUES (1, 'stratosphere', 1),
|
|||||||
(2, 'ants from up above',2),
|
(2, 'ants from up above',2),
|
||||||
(3, 'vespertine',3),
|
(3, 'vespertine',3),
|
||||||
(4, 'contemporary movement', 1);
|
(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');
|
||||||
|
|||||||
Vendored
+15
@@ -3855,3 +3855,18 @@ $_$ language sql;
|
|||||||
create or replace function test.get_tiobe_pls() returns setof test.tiobe_pls as $$
|
create or replace function test.get_tiobe_pls() returns setof test.tiobe_pls as $$
|
||||||
select * from test.tiobe_pls;
|
select * from test.tiobe_pls;
|
||||||
$$ language sql;
|
$$ 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
|
||||||
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user