fix: aliasing on computed rels

This commit is contained in:
steve-chavez
2022-10-19 19:49:43 -05:00
committed by Steve Chavez
parent c8b39c6cde
commit 7ace8ace49
6 changed files with 56 additions and 15 deletions
+2
View File
@@ -9,6 +9,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- #2401, #2444, Fix SIGUSR1 to fully flush connections pool, remove `db-pool-timeout`. - @robx - #2401, #2444, Fix SIGUSR1 to fully flush connections pool, remove `db-pool-timeout`. - @robx
- #2348, Add `db-pool-acquisition-timeout` configuration option, time in seconds to wait to acquire a connection. - @robx - #2348, Add `db-pool-acquisition-timeout` configuration option, time in seconds to wait to acquire a connection. - @robx
- #2428, Fix opening an empty transaction on failed resource embedding - @steve-chavez
- #2455, Fix embedding the same table multiple times - @steve-chavez
### Deprecated ### Deprecated
+15 -14
View File
@@ -126,23 +126,24 @@ treeRestrictRange maxRows _ request = pure $ nodeRestrictRange maxRows <$> reque
nodeRestrictRange :: Maybe Integer -> ReadPlan -> ReadPlan nodeRestrictRange :: Maybe Integer -> ReadPlan -> ReadPlan
nodeRestrictRange m q@ReadPlan{range_=r} = q{range_=restrictRange m r } nodeRestrictRange m q@ReadPlan{range_=r} = q{range_=restrictRange m r }
-- add relationships to the nodes of the tree by traversing the forest while keeping track of the parentNode -- add relationships to the nodes of the tree by traversing the forest while keeping track of the parentNode, also adds aliasing
addRels :: Schema -> Action -> RelationshipsMap -> Maybe ReadPlanTree -> ReadPlanTree -> Either ApiRequestError ReadPlanTree addRels :: Schema -> Action -> RelationshipsMap -> Maybe ReadPlanTree -> ReadPlanTree -> Either ApiRequestError ReadPlanTree
addRels schema action allRels parentNode (Node rPlan@ReadPlan{from=tbl,relName,relHint,depth} forest) = addRels schema action allRels parentNode (Node rPlan@ReadPlan{relName,relHint,depth} forest) =
case parentNode of case parentNode of
Just (Node ReadPlan{from=parentNodeQi, fromAlias} _) -> Just (Node ReadPlan{from=parentNodeQi, fromAlias} _) ->
let newFrom r = if qiName tbl == relName then relForeignTable r else tbl let
newReadPlan = (\r -> newReadPlan = (\r ->
if not $ relIsSelf r -- add alias if self rel let newAlias = Just (qiName (relForeignTable r) <> "_" <> show depth) in
then rPlan{from=newFrom r, relToParent=Just r, relJoinConds=getJoinConditions Nothing fromAlias r} case r of
else Relationship{relCardinality=M2M _} ->
let selfAlias = Just (qiName (newFrom r) <> "_" <> show depth) in rPlan{from=relForeignTable r, relToParent=Just r, relJoinConds=getJoinConditions Nothing fromAlias r}
rPlan{from=newFrom r, relToParent=Just r, fromAlias=selfAlias, relJoinConds=getJoinConditions selfAlias fromAlias r} _ ->
) <$> rel rPlan{from=relForeignTable r, relToParent=Just r, fromAlias=newAlias, relJoinConds=getJoinConditions newAlias fromAlias r}
origin = if depth == 1 -- Only on depth 1 we check if the root(depth 0) has an alias so the sourceCTEName alias can be found as a relationship ) <$> rel
then fromMaybe (qiName parentNodeQi) fromAlias origin = if depth == 1 -- Only on depth 1 we check if the root(depth 0) has an alias so the sourceCTEName alias can be found as a relationship
else qiName parentNodeQi then fromMaybe (qiName parentNodeQi) fromAlias
rel = findRel schema allRels origin relName relHint else qiName parentNodeQi
rel = findRel schema allRels origin relName relHint
in in
Node <$> newReadPlan <*> (updateForest . hush $ Node <$> newReadPlan <*> pure forest) Node <$> newReadPlan <*> (updateForest . hush $ Node <$> newReadPlan <*> pure forest)
Nothing -> -- root case Nothing -> -- root case
-1
View File
@@ -32,7 +32,6 @@ data ReadPlan = ReadPlan
{ select :: [SelectItem] { select :: [SelectItem]
, from :: QualifiedIdentifier , from :: QualifiedIdentifier
, fromAlias :: Maybe Alias , fromAlias :: Maybe Alias
-- ^ A table alias is used in case of self joins
, where_ :: [LogicTree] , where_ :: [LogicTree]
, order :: [OrderTerm] , order :: [OrderTerm]
, range_ :: NonnegRange , range_ :: NonnegRange
@@ -107,3 +107,12 @@ spec = describe "computed relationships" $ do
get "/second_1?select=*,first_1(*)" get "/second_1?select=*,first_1(*)"
`shouldRespondWith` `shouldRespondWith`
[json|[]|] { matchHeaders = [matchContentTypeJson] } [json|[]|] { matchHeaders = [matchContentTypeJson] }
-- https://github.com/PostgREST/postgrest/issues/2455
it "creates queries with the right aliasing" $ do
get "/fee?select=*,jsbaz(*,janedoe(*))"
`shouldRespondWith`
[json|[]|] { matchHeaders = [matchContentTypeJson] }
get "/fee?select=*,jsbaz(*,johnsmith(*, fee(*)))"
`shouldRespondWith`
[json|[]|] { matchHeaders = [matchContentTypeJson] }
+4
View File
@@ -210,6 +210,10 @@ GRANT ALL ON TABLE
, second , second
, first_1 , first_1
, second_1 , second_1
, fee
, baz
, janedoe
, johnsmith
TO postgrest_test_anonymous; TO postgrest_test_anonymous;
GRANT INSERT ON TABLE insertonly TO postgrest_test_anonymous; GRANT INSERT ON TABLE insertonly TO postgrest_test_anonymous;
+26
View File
@@ -2836,3 +2836,29 @@ $$ LANGUAGE sql STABLE ROWS 1;
CREATE FUNCTION test.first_1(test.second_1) RETURNS SETOF test.first_1 AS $$ CREATE FUNCTION test.first_1(test.second_1) RETURNS SETOF test.first_1 AS $$
SELECT * FROM test.first_1 WHERE second_id_1 = $1.id; SELECT * FROM test.first_1 WHERE second_id_1 = $1.id;
$$ LANGUAGE sql STABLE ROWS 1; $$ LANGUAGE sql STABLE ROWS 1;
create table fee (
fee_id int primary key
);
create table baz (
baz_id int primary key
);
create table janedoe (
janedoe_id int primary key,
baz_id int references baz(baz_id)
);
create table johnsmith (
johnsmith_id int primary key,
fee_id int references fee(fee_id),
baz_id int references baz(baz_id)
);
create or replace function jsbaz(fee) returns setof baz as $$
select b.*
from baz b
join johnsmith js on js.baz_id = b.baz_id
where js.fee_id = $1.fee_id
$$ stable language sql;