fix: RPCs not embedding correctly when using overloaded functions for computed relationships
This commit is contained in:
committed by
Steve Chavez
parent
de97f646a4
commit
5c822b7ec4
@@ -17,6 +17,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- #2846, Fix error when requesting `Prefer: count=<type>` and doing null filtering on embedded resources - @laurenceisla
|
- #2846, Fix error when requesting `Prefer: count=<type>` and doing null filtering on embedded resources - @laurenceisla
|
||||||
- #2959, Fix setting `default_transaction_isolation` unnecessarily - @steve-chavez
|
- #2959, Fix setting `default_transaction_isolation` unnecessarily - @steve-chavez
|
||||||
- #2929, Fix arrow filtering on RPC returning dynamic TABLE with composite type - @steve-chavez
|
- #2929, Fix arrow filtering on RPC returning dynamic TABLE with composite type - @steve-chavez
|
||||||
|
- #2963, Fix RPCs not embedding correctly when using overloaded functions for computed relationships - @laurenceisla
|
||||||
|
|
||||||
## [11.2.0] - 2023-08-10
|
## [11.2.0] - 2023-08-10
|
||||||
|
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ addRels schema action allRels parentNode (Node rPlan@ReadPlan{relName,relHint,re
|
|||||||
Relationship{relCardinality=M2M _} -> -- m2m does internal implicit joins that don't need aliasing
|
Relationship{relCardinality=M2M _} -> -- m2m does internal implicit joins that don't need aliasing
|
||||||
rPlan{from=relForeignTable r, relToParent=Just r, relAggAlias=aggAlias, relJoinConds=getJoinConditions Nothing parentAlias r}
|
rPlan{from=relForeignTable r, relToParent=Just r, relAggAlias=aggAlias, relJoinConds=getJoinConditions Nothing parentAlias r}
|
||||||
ComputedRelationship{} ->
|
ComputedRelationship{} ->
|
||||||
rPlan{from=relForeignTable r, relToParent=Just r{relTable=maybe (relTable r) (QualifiedIdentifier mempty) parentAlias}, relAggAlias=aggAlias, fromAlias=newAlias}
|
rPlan{from=relForeignTable r, relToParent=Just r{relTableAlias=maybe (relTable r) (QualifiedIdentifier mempty) parentAlias}, relAggAlias=aggAlias, fromAlias=newAlias}
|
||||||
_ ->
|
_ ->
|
||||||
rPlan{from=relForeignTable r, relToParent=Just r, relAggAlias=aggAlias, fromAlias=newAlias, relJoinConds=getJoinConditions newAlias parentAlias r}
|
rPlan{from=relForeignTable r, relToParent=Just r, relAggAlias=aggAlias, fromAlias=newAlias, relJoinConds=getJoinConditions newAlias parentAlias r}
|
||||||
) <$> rel
|
) <$> rel
|
||||||
|
|||||||
@@ -242,8 +242,10 @@ getQualifiedIdentifier rel mainQi tblAlias = case rel of
|
|||||||
fromF :: Maybe Relationship -> QualifiedIdentifier -> Maybe Alias -> SQL.Snippet
|
fromF :: Maybe Relationship -> QualifiedIdentifier -> Maybe Alias -> SQL.Snippet
|
||||||
fromF rel mainQi tblAlias = "FROM " <>
|
fromF rel mainQi tblAlias = "FROM " <>
|
||||||
(case rel of
|
(case rel of
|
||||||
Just ComputedRelationship{relFunction,relTable} -> fromQi relFunction <> "(" <> pgFmtIdent (qiName relTable) <> ")"
|
-- Due to the use of CTEs on RPC, we need to cast the parameter to the table name in case of function overloading.
|
||||||
_ -> fromQi mainQi) <>
|
-- See https://github.com/PostgREST/postgrest/issues/2963#issuecomment-1736557386
|
||||||
|
Just ComputedRelationship{relFunction,relTableAlias,relTable} -> fromQi relFunction <> "(" <> pgFmtIdent (qiName relTableAlias) <> "::" <> fromQi relTable <> ")"
|
||||||
|
_ -> fromQi mainQi) <>
|
||||||
maybe mempty (\a -> " AS " <> pgFmtIdent a) tblAlias <>
|
maybe mempty (\a -> " AS " <> pgFmtIdent a) tblAlias <>
|
||||||
(case rel of
|
(case rel of
|
||||||
Just Relationship{relCardinality=M2M Junction{junTable=jt}} -> ", " <> fromQi jt
|
Just Relationship{relCardinality=M2M Junction{junTable=jt}} -> ", " <> fromQi jt
|
||||||
|
|||||||
@@ -882,6 +882,7 @@ allComputedRels =
|
|||||||
(QualifiedIdentifier <$> column HD.text <*> column HD.text) <*>
|
(QualifiedIdentifier <$> column HD.text <*> column HD.text) <*>
|
||||||
(QualifiedIdentifier <$> column HD.text <*> column HD.text) <*>
|
(QualifiedIdentifier <$> column HD.text <*> column HD.text) <*>
|
||||||
(QualifiedIdentifier <$> column HD.text <*> column HD.text) <*>
|
(QualifiedIdentifier <$> column HD.text <*> column HD.text) <*>
|
||||||
|
pure (QualifiedIdentifier mempty mempty) <*>
|
||||||
column HD.bool <*>
|
column HD.bool <*>
|
||||||
column HD.bool
|
column HD.bool
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ data Relationship = Relationship
|
|||||||
{ relFunction :: QualifiedIdentifier
|
{ relFunction :: QualifiedIdentifier
|
||||||
, relTable :: QualifiedIdentifier
|
, relTable :: QualifiedIdentifier
|
||||||
, relForeignTable :: QualifiedIdentifier
|
, relForeignTable :: QualifiedIdentifier
|
||||||
|
, relTableAlias :: QualifiedIdentifier
|
||||||
, relToOne :: Bool
|
, relToOne :: Bool
|
||||||
, relIsSelf :: Bool
|
, relIsSelf :: Bool
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,3 +192,29 @@ spec = describe "computed relationships" $ do
|
|||||||
{"name":"Windows 10","computed_clients":{"name":"Microsoft"}}
|
{"name":"Windows 10","computed_clients":{"name":"Microsoft"}}
|
||||||
]}
|
]}
|
||||||
]|] { matchHeaders = [matchContentTypeJson] }
|
]|] { matchHeaders = [matchContentTypeJson] }
|
||||||
|
|
||||||
|
-- https://github.com/PostgREST/postgrest/issues/2963
|
||||||
|
context "can be defined using overloaded functions" $ do
|
||||||
|
it "tables" $ do
|
||||||
|
get "/items?select=*,computed_rel_overload(*)&limit=1"
|
||||||
|
`shouldRespondWith`
|
||||||
|
[json|
|
||||||
|
[{"id":1,"computed_rel_overload":[{"id":1}]}]
|
||||||
|
|] { matchHeaders = [matchContentTypeJson] }
|
||||||
|
get "/items2?select=*,computed_rel_overload(*)&limit=1"
|
||||||
|
`shouldRespondWith`
|
||||||
|
[json|
|
||||||
|
[{"id":1,"computed_rel_overload":[{"id":1},{"id":2}]}]
|
||||||
|
|] { matchHeaders = [matchContentTypeJson] }
|
||||||
|
|
||||||
|
it "rpc" $ do
|
||||||
|
get "/rpc/search?id=1&select=*,computed_rel_overload(*)"
|
||||||
|
`shouldRespondWith`
|
||||||
|
[json|
|
||||||
|
[{"id":1,"computed_rel_overload":[{"id":1}]}]
|
||||||
|
|] { matchHeaders = [matchContentTypeJson] }
|
||||||
|
get "/rpc/search2?id=1&select=*,computed_rel_overload(*)"
|
||||||
|
`shouldRespondWith`
|
||||||
|
[json|
|
||||||
|
[{"id":1,"computed_rel_overload":[{"id":1},{"id":2}]}]
|
||||||
|
|] { matchHeaders = [matchContentTypeJson] }
|
||||||
|
|||||||
Vendored
+15
@@ -3456,3 +3456,18 @@ returns table(id int, val complex) as $$
|
|||||||
union
|
union
|
||||||
select 3, row(0.3, 0.7)::complex as val;
|
select 3, row(0.3, 0.7)::complex as val;
|
||||||
$$ language sql;
|
$$ language sql;
|
||||||
|
|
||||||
|
create function computed_rel_overload(items) returns setof items2 as $$
|
||||||
|
select * from items2 limit 1
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
create function computed_rel_overload(items2) returns setof items2 as $$
|
||||||
|
select * from items2 limit 2
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
create function search2(id bigint) returns setof items2
|
||||||
|
language plpgsql
|
||||||
|
stable
|
||||||
|
as $$ begin
|
||||||
|
return query select items2.id from items2 where items2.id=search2.id;
|
||||||
|
end$$;
|
||||||
|
|||||||
Reference in New Issue
Block a user