Skip to content

Commit 6009c5f

Browse files
committed
WIP: Add functions to POST path
1 parent 811234c commit 6009c5f

File tree

5 files changed

+801
-8
lines changed

5 files changed

+801
-8
lines changed

sql/components.sql

Lines changed: 145 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ returns jsonb language sql stable as
1919
$$
2020
select oas_build_component_schemas_from_tables_and_composite_types(schemas) ||
2121
oas_build_component_schemas_from_functions_return_types(schemas) ||
22+
oas_build_component_schemas_from_functions_arguments(schemas) ||
2223
oas_build_component_schemas_headers()
2324
$$;
2425

@@ -180,6 +181,81 @@ from (
180181
) x;
181182
$$;
182183

184+
create or replace function oas_build_component_schemas_from_functions_arguments(schemas text[])
185+
returns jsonb language sql stable as
186+
$$
187+
with all_functions_with_arguments as (
188+
-- Build Component Schemas for IN/INOUT function arguments
189+
select *, argument_name = '' and argument_input_qty = 1 as argument_is_single_unnamed
190+
from postgrest_get_all_functions(schemas)
191+
where argument_input_qty > 0
192+
and (argument_is_in or argument_is_inout or argument_is_variadic)
193+
),
194+
aggregated_function_arguments as (
195+
select
196+
function_schema,
197+
function_full_name,
198+
function_description,
199+
argument_is_single_unnamed,
200+
array_agg(argument_name order by argument_position) filter (where argument_is_required) AS required_arguments,
201+
-- Build objects for functions with one or more named arguments
202+
case when not argument_is_single_unnamed then
203+
jsonb_object_agg(
204+
argument_name,
205+
case when argument_item_type_name is null and argument_is_composite then
206+
oas_build_reference_to_schemas(argument_composite_full_name)
207+
else
208+
oas_schema_object(
209+
type := postgrest_pgtype_to_oastype(argument_type_name),
210+
format := argument_type_name::text,
211+
items :=
212+
case
213+
when argument_item_type_name is null then
214+
null
215+
when argument_is_composite then
216+
oas_build_reference_to_schemas(argument_composite_full_name)
217+
else
218+
oas_schema_object(
219+
type := postgrest_pgtype_to_oastype(argument_item_type_name),
220+
format := argument_item_type_name::text
221+
)
222+
end
223+
)
224+
end
225+
order by argument_position
226+
)
227+
-- For functions with a single unnamed parameter, build the Schema according to the parameter type
228+
else
229+
jsonb_agg(
230+
oas_schema_object(
231+
type := postgrest_pgtype_to_oastype(argument_type_name),
232+
format := argument_type_name::text
233+
)
234+
)
235+
end as arguments
236+
from all_functions_with_arguments
237+
group by function_schema, function_full_name, function_description, argument_is_single_unnamed
238+
)
239+
select jsonb_object_agg(x.component_name, x.oas_schema)
240+
from (
241+
select
242+
'rpc.args.' || function_full_name as component_name,
243+
case when not argument_is_single_unnamed then
244+
oas_schema_object(
245+
description := function_description,
246+
properties := coalesce(arguments, '{}'),
247+
type := 'object',
248+
required := required_arguments
249+
)
250+
else
251+
-- We take the first and only element, since there's just one single unnamed argument
252+
arguments->0
253+
end as oas_schema
254+
from
255+
aggregated_function_arguments
256+
) x;
257+
$$;
258+
183259
create or replace function oas_build_component_schemas_headers()
184260
returns jsonb language sql stable as
185261
$$
@@ -304,6 +380,7 @@ returns jsonb language sql stable as
304380
$$
305381
select oas_build_component_parameters_query_params_from_tables(schemas) ||
306382
oas_build_component_parameters_query_params_from_function_args(schemas) ||
383+
oas_build_component_parameters_query_params_from_function_ret(schemas) ||
307384
oas_build_component_parameters_query_params_common() ||
308385
oas_build_component_parameters_headers_common();
309386
$$;
@@ -322,14 +399,42 @@ from (
322399
)
323400
) as param_schema
324401
from (
325-
select table_full_name, column_name
326-
from postgrest_get_all_tables_and_composite_types()
327-
where table_schema = any(schemas)
328-
and (is_table or is_view)
402+
select table_full_name, column_name
403+
from postgrest_get_all_tables_and_composite_types()
404+
where (
405+
table_schema = any(schemas)
406+
and (is_table or is_view)
407+
)
408+
-- composite type columns can also be used as row filters if a function returns it
409+
or exists (
410+
select 1
411+
from postgrest_get_all_functions(schemas)
412+
where return_type_composite_relid = table_oid
413+
)
329414
) _
330415
) x;
331416
$$;
332417

418+
-- Builds "rowFilter"s for functions returning TABLE or INOUT/OUT types
419+
create or replace function oas_build_component_parameters_query_params_from_function_ret(schemas text[])
420+
returns jsonb language sql stable as
421+
$$
422+
select jsonb_object_agg(x.param_name, x.param_schema)
423+
from (
424+
select format('rowFilter.rpc.%1$s.%2$s', function_full_name, argument_name) as param_name,
425+
oas_parameter_object(
426+
name := argument_name,
427+
"in" := 'query',
428+
schema := oas_schema_object(
429+
type := 'string'
430+
)
431+
) as param_schema
432+
from postgrest_get_all_functions(schemas)
433+
where argument_name <> ''
434+
and (argument_is_inout or argument_is_out or argument_is_table)
435+
) x;
436+
$$;
437+
333438
create or replace function oas_build_component_parameters_query_params_from_function_args(schemas text[])
334439
returns jsonb language sql stable as
335440
$$
@@ -882,7 +987,8 @@ $$;
882987
create or replace function oas_build_request_bodies(schemas text[])
883988
returns jsonb language sql stable as
884989
$$
885-
select oas_build_request_bodies_from_tables(schemas);
990+
select oas_build_request_bodies_from_tables(schemas) ||
991+
oas_build_request_bodies_from_functions(schemas);
886992
$$;
887993

888994
create or replace function oas_build_request_bodies_from_tables(schemas text[])
@@ -928,6 +1034,40 @@ from (
9281034
) as x;
9291035
$$;
9301036

1037+
create or replace function oas_build_request_bodies_from_functions(schemas text[])
1038+
returns jsonb language sql stable as
1039+
$$
1040+
select jsonb_object_agg('rpc.' || x.function_full_name, x.oas_req_body)
1041+
from (
1042+
select
1043+
function_full_name,
1044+
oas_request_body_object(
1045+
description := function_full_name,
1046+
required := argument_default_qty < argument_input_qty,
1047+
content := jsonb_build_object(
1048+
'application/json',
1049+
oas_media_type_object(
1050+
"schema" := oas_build_reference_to_schemas('rpc.args.' || function_full_name)
1051+
),
1052+
'application/x-www-form-urlencoded',
1053+
oas_media_type_object(
1054+
"schema" := oas_build_reference_to_schemas('rpc.args.' || function_full_name)
1055+
),
1056+
'text/csv',
1057+
oas_media_type_object(
1058+
"schema" := oas_schema_object(
1059+
type := 'string',
1060+
format := 'csv'
1061+
)
1062+
)
1063+
)
1064+
) as oas_req_body
1065+
from postgrest_get_all_functions(schemas)
1066+
where argument_input_qty > 0
1067+
group by function_full_name, argument_input_qty, argument_default_qty
1068+
) as x;
1069+
$$;
1070+
9311071
-- Security Schemes
9321072

9331073
create or replace function oas_build_component_security_schemes ()

sql/paths.sql

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,73 @@ from (
189189
'default',
190190
oas_build_reference_to_responses('defaultError', 'Error')
191191
)
192+
),
193+
post := oas_operation_object(
194+
summary := (postgrest_unfold_comment(function_description))[1],
195+
description := (postgrest_unfold_comment(function_description))[2],
196+
tags := array['(rpc) ' || function_name],
197+
requestBody := case when argument_input_qty > 0 then oas_build_reference_to_request_bodies('rpc.' || function_full_name) end,
198+
parameters :=
199+
-- TODO: The row filters for functions returning TABLE, OUT, INOUT and composite types should also work for the GET path.
200+
-- Right now they're not included in GET, because the argument names (in rpcParams) could clash with the name of the return type columns (in rowFilter).
201+
coalesce(
202+
jsonb_agg(
203+
oas_build_reference_to_parameters(format('rowFilter.rpc.%1$s.%2$s', function_full_name, argument_name))
204+
) filter ( where argument_name <> '' and (argument_is_inout or argument_is_out or argument_is_table)),
205+
'[]'
206+
) ||
207+
return_composite_param_ref ||
208+
case when return_type_is_table or return_type_is_out or return_type_composite_relid <> 0 then
209+
jsonb_build_array(
210+
oas_build_reference_to_parameters('select'),
211+
oas_build_reference_to_parameters('order'),
212+
oas_build_reference_to_parameters('limit'),
213+
oas_build_reference_to_parameters('offset'),
214+
oas_build_reference_to_parameters('or'),
215+
oas_build_reference_to_parameters('and'),
216+
oas_build_reference_to_parameters('not.or'),
217+
oas_build_reference_to_parameters('not.and'),
218+
oas_build_reference_to_parameters('preferPostRpc')
219+
)
220+
else
221+
jsonb_build_array(
222+
oas_build_reference_to_parameters('preferPostRpc')
223+
)
224+
end,
225+
responses :=
226+
case when return_type_is_set then
227+
jsonb_build_object(
228+
'200',
229+
oas_build_reference_to_responses('rpc.' || function_full_name, 'OK'),
230+
'206',
231+
oas_build_reference_to_responses('rpc.' || function_full_name, 'Partial Content')
232+
)
233+
else
234+
jsonb_build_object(
235+
'200',
236+
oas_build_reference_to_responses('rpc.' || function_full_name, 'OK')
237+
)
238+
end ||
239+
jsonb_build_object(
240+
'default',
241+
oas_build_reference_to_responses('defaultError', 'Error')
242+
)
192243
)
193244
) as oas_path_item
194245
from (
195-
select function_name, function_full_name, function_description, return_type_name, return_type_is_set, return_type_is_table, return_type_is_out, return_type_composite_relid, argument_name, argument_is_in, argument_is_inout, argument_is_variadic
196-
from postgrest_get_all_functions(schemas)
246+
select function_name, function_full_name, function_description, return_type_name, return_type_is_set, return_type_is_table, return_type_is_out, return_type_composite_relid, argument_name, argument_is_in, argument_is_inout, argument_is_out, argument_is_table, argument_is_variadic, argument_input_qty,
247+
comp.return_composite_param_ref
248+
from postgrest_get_all_functions(schemas) f
249+
left join lateral (
250+
select coalesce(jsonb_agg(oas_build_reference_to_parameters(format('rowFilter.%1$s.%2$s', table_full_name, column_name))),'[]') as return_composite_param_ref
251+
from (
252+
select c.table_full_name, c.column_name
253+
from postgrest_get_all_tables_and_composite_types() c
254+
where f.return_type_composite_relid = c.table_oid
255+
) _
256+
) comp on true
197257
) _
198-
group by function_name, function_full_name, function_description, return_type_name, return_type_is_set, return_type_is_table, return_type_is_out, return_type_composite_relid
258+
group by function_name, function_full_name, function_description, return_type_name, return_type_is_set, return_type_is_table, return_type_is_out, return_type_composite_relid, argument_input_qty, return_composite_param_ref
199259
) x;
200260
$$;
201261

sql/postgrest.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ $$;
166166
create or replace function postgrest_get_all_functions(schemas text[])
167167
returns table (
168168
argument_input_qty int,
169+
argument_default_qty int,
169170
argument_name text,
170171
argument_reg_type oid,
171172
argument_type_name text,
@@ -225,6 +226,7 @@ $$
225226
all_functions AS (
226227
SELECT
227228
p.pronargs AS argument_input_qty,
229+
p.pronargdefaults AS argument_default_qty,
228230
COALESCE(pa.name, '') AS argument_name,
229231
pa.type AS argument_reg_type,
230232
format_type(ta.oid, NULL::integer) AS argument_type_name,

0 commit comments

Comments
 (0)