fix: Avoid casting to table type when select= and media type handler are used
Previously using a generic mimetype handler failed when any kind of select= was given, because we tried to cast the select-result to the original table type. With this change, this cast is only applied when select=* is given implicitly or explicitly. This is the only case where this makes sense, because this guarantees that correct columns are selected in the correct order for this cast to succeed. Resolves #3160
This commit is contained in:
@@ -230,6 +230,76 @@ spec = describe "custom media types" $ do
|
||||
simpleHeaders r `shouldContain` [("Content-Type", "text/csv; charset=utf-8")]
|
||||
simpleHeaders r `shouldContain` [("Content-Disposition", "attachment; filename=\"lines.csv\"")]
|
||||
|
||||
-- https://github.com/PostgREST/postgrest/issues/3160
|
||||
context "using select query parameter" $ do
|
||||
it "without select" $ do
|
||||
request methodGet "/projects?id=in.(1,2)" (acceptHdrs "pg/outfunc") ""
|
||||
`shouldRespondWith`
|
||||
[str|(1,"Windows 7",1)
|
||||
|(2,"Windows 10",1)
|
||||
|]
|
||||
{ matchStatus = 200
|
||||
, matchHeaders = ["Content-Type" <:> "pg/outfunc"]
|
||||
}
|
||||
|
||||
it "with fewer columns selected" $ do
|
||||
request methodGet "/projects?id=in.(1,2)&select=id,name" (acceptHdrs "pg/outfunc") ""
|
||||
`shouldRespondWith`
|
||||
[str|(1,"Windows 7")
|
||||
|(2,"Windows 10")
|
||||
|]
|
||||
{ matchStatus = 200
|
||||
, matchHeaders = ["Content-Type" <:> "pg/outfunc"]
|
||||
}
|
||||
|
||||
it "with columns in different order" $ do
|
||||
request methodGet "/projects?id=in.(1,2)&select=name,id,client_id" (acceptHdrs "pg/outfunc") ""
|
||||
`shouldRespondWith`
|
||||
[str|("Windows 7",1,1)
|
||||
|("Windows 10",2,1)
|
||||
|]
|
||||
{ matchStatus = 200
|
||||
, matchHeaders = ["Content-Type" <:> "pg/outfunc"]
|
||||
}
|
||||
|
||||
it "with computed columns" $ do
|
||||
request methodGet "/items?id=in.(1,2)&select=id,always_true" (acceptHdrs "pg/outfunc") ""
|
||||
`shouldRespondWith`
|
||||
[str|(1,t)
|
||||
|(2,t)
|
||||
|]
|
||||
{ matchStatus = 200
|
||||
, matchHeaders = ["Content-Type" <:> "pg/outfunc"]
|
||||
}
|
||||
|
||||
-- TODO: Embeddings should not return JSON. Arrays of record would be much better.
|
||||
it "with embedding" $ do
|
||||
request methodGet "/projects?id=in.(1,2)&select=*,clients(id)" (acceptHdrs "pg/outfunc") ""
|
||||
`shouldRespondWith`
|
||||
[str|(1,"Windows 7",1,"{""id"": 1}")
|
||||
|(2,"Windows 10",1,"{""id"": 1}")
|
||||
|]
|
||||
{ matchStatus = 200
|
||||
, matchHeaders = ["Content-Type" <:> "pg/outfunc"]
|
||||
}
|
||||
|
||||
it "will fail for specific aggregate with fewer columns" $ do
|
||||
request methodGet "/lines?select=id" (acceptHdrs "application/vnd.twkb") ""
|
||||
`shouldRespondWith` 406
|
||||
|
||||
it "will fail for specific aggregate with more columns" $ do
|
||||
request methodGet "/lines?select=id,name,geom,id" (acceptHdrs "application/vnd.twkb") ""
|
||||
`shouldRespondWith` 406
|
||||
|
||||
it "will fail for specific aggregate with columns in different order" $ do
|
||||
request methodGet "/lines?select=name,id,geom" (acceptHdrs "application/vnd.twkb") ""
|
||||
`shouldRespondWith` 406
|
||||
|
||||
-- This is just because it would be hard to detect this case, so we better error in this case, too.
|
||||
it "will fail for specific aggregate with columns in same order" $ do
|
||||
request methodGet "/lines?select=id,name,geom" (acceptHdrs "application/vnd.twkb") ""
|
||||
`shouldRespondWith` 406
|
||||
|
||||
context "any media type" $ do
|
||||
context "on functions" $ do
|
||||
it "returns application/json for */* if not explicitly set" $ do
|
||||
|
||||
Vendored
+15
-2
@@ -3550,8 +3550,8 @@ returns "application/vnd.geo2+json" as $$
|
||||
select (jsonb_build_object('type', 'FeatureCollection', 'hello', 'world'))::"application/vnd.geo2+json";
|
||||
$$ language sql;
|
||||
|
||||
drop aggregate if exists test.geo2json_agg(anyelement);
|
||||
create aggregate test.geo2json_agg(anyelement) (
|
||||
drop aggregate if exists test.geo2json_agg_any(anyelement);
|
||||
create aggregate test.geo2json_agg_any(anyelement) (
|
||||
initcond = '[]'
|
||||
, stype = "application/vnd.geo2+json"
|
||||
, sfunc = geo2json_trans
|
||||
@@ -3755,3 +3755,16 @@ create aggregate test.some_agg (some_numbers) (
|
||||
|
||||
create view bad_subquery as
|
||||
select * from projects where id = (select id from projects);
|
||||
|
||||
-- custom generic mimetype
|
||||
create domain "pg/outfunc" as text;
|
||||
create function test.outfunc_trans (state text, next anyelement)
|
||||
returns "pg/outfunc" as $$
|
||||
select (state || next::text || E'\n')::"pg/outfunc";
|
||||
$$ language sql;
|
||||
|
||||
create aggregate test.outfunc_agg (anyelement) (
|
||||
initcond = ''
|
||||
, stype = "pg/outfunc"
|
||||
, sfunc = outfunc_trans
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user