diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a4014e0b..bad4f5199 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - #2862, Fix null filtering on embedded resource when using a column name equal to the relation name - @steve-chavez - #1586, Fix function parameters of type character and bit not ignoring length - @laurenceisla + Fixes the error "value too long for type character(1)" when the char length of the parameter was bigger than one. + - #2881, Fix error when a function returns `RECORD` or `SET OF RECORD` - @laurenceisla ## [11.1.0] - 2023-06-07 diff --git a/src/PostgREST/Query/QueryBuilder.hs b/src/PostgREST/Query/QueryBuilder.hs index cff4c44f0..fb6408a2a 100644 --- a/src/PostgREST/Query/QueryBuilder.hs +++ b/src/PostgREST/Query/QueryBuilder.hs @@ -165,7 +165,7 @@ mutatePlanToQuery (Delete mainQi logicForest range ordts returnings) callPlanToQuery :: CallPlan -> PgVersion -> SQL.Snippet callPlanToQuery (FunctionCall qi params args returnsScalar returnsSetOfScalar returnsCompositeAlias returnings) pgVer = - "SELECT " <> (if returnsScalar || returnsSetOfScalar then "pgrst_call AS pgrst_scalar " else returnedColumns) <> " " <> + "SELECT " <> (if returnsScalar || returnsSetOfScalar then "pgrst_call.pgrst_scalar" else returnedColumns) <> " " <> fromCall where fromCall = case params of @@ -176,6 +176,7 @@ callPlanToQuery (FunctionCall qi params args returnsScalar returnsSetOfScalar re callIt :: SQL.Snippet -> SQL.Snippet callIt argument | pgVer < pgVersion130 && pgVer >= pgVersion110 && returnsCompositeAlias = "(SELECT (" <> fromQi qi <> "(" <> argument <> ")).*) pgrst_call" + | returnsScalar || returnsSetOfScalar = "(SELECT " <> fromQi qi <> "(" <> argument <> ") pgrst_scalar) pgrst_call" | otherwise = fromQi qi <> "(" <> argument <> ") pgrst_call" fmtParams :: [RoutineParam] -> SQL.Snippet diff --git a/test/spec/Feature/Query/RpcSpec.hs b/test/spec/Feature/Query/RpcSpec.hs index 56e28165d..98a73a002 100644 --- a/test/spec/Feature/Query/RpcSpec.hs +++ b/test/spec/Feature/Query/RpcSpec.hs @@ -475,6 +475,27 @@ spec actualPgVersion = `shouldRespondWith` [json|null|] + when (actualPgVersion >= pgVersion110) $ do + it "returns a record type" $ do + post "/rpc/returns_record" + "" + `shouldRespondWith` + [json|{"id":1,"name":"Windows 7","client_id":1}|] + post "/rpc/returns_record_params" + [json|{"id":1, "name": "Windows%"}|] + `shouldRespondWith` + [json|{"id":1,"name":"Windows 7","client_id":1}|] + + it "returns a setof record type" $ do + post "/rpc/returns_setof_record" + "" + `shouldRespondWith` + [json|[{"id":1,"name":"Windows 7","client_id":1},{"id":2,"name":"Windows 10","client_id":1}]|] + post "/rpc/returns_setof_record_params" + [json|{"id":1,"name":"Windows%"}|] + `shouldRespondWith` + [json|[{"id":1,"name":"Windows 7","client_id":1},{"id":2,"name":"Windows 10","client_id":1}]|] + context "different types when overloaded" $ do it "returns composite type" $ post "/rpc/ret_point_overloaded" diff --git a/test/spec/fixtures/schema.sql b/test/spec/fixtures/schema.sql index 5fb2ecd74..8d19d7676 100644 --- a/test/spec/fixtures/schema.sql +++ b/test/spec/fixtures/schema.sql @@ -3352,3 +3352,19 @@ create or replace function bit_param_insert(bit_ bit(4), bit_arr bit(4)[]) returns void as $$ insert into bitchar_with_length(bit, bit_arr) values($1, $2); $$ language sql; + +create function returns_record() returns record as $$ +select * from projects limit 1; +$$ language sql; + +create function returns_record_params(id int, name text) returns record as $$ +select * from projects p where p.id = $1 and p.name like $2; +$$ language sql; + +create function returns_setof_record() returns setof record as $$ +select * from projects limit 2; +$$ language sql; + +create function returns_setof_record_params(id int, name text) returns setof record as $$ +select * from projects p where p.id >= $1 and p.name like $2; +$$ language sql;