functions.ts114 lines · main
1import { safeSql } from '../pg-format'
2
3export const FUNCTIONS_SQL = /* SQL */ safeSql`
4-- CTE with sane arg_modes, arg_names, and arg_types.
5-- All three are always of the same length.
6-- All three include all args, including OUT and TABLE args.
7with functions as (
8 select
9 *,
10 -- proargmodes is null when all arg modes are IN
11 coalesce(
12 p.proargmodes,
13 array_fill('i'::text, array[cardinality(coalesce(p.proallargtypes, p.proargtypes))])
14 ) as arg_modes,
15 -- proargnames is null when all args are unnamed
16 coalesce(
17 p.proargnames,
18 array_fill(''::text, array[cardinality(coalesce(p.proallargtypes, p.proargtypes))])
19 ) as arg_names,
20 -- proallargtypes is null when all arg modes are IN
21 coalesce(p.proallargtypes, p.proargtypes) as arg_types,
22 array_cat(
23 array_fill(false, array[pronargs - pronargdefaults]),
24 array_fill(true, array[pronargdefaults])) as arg_has_defaults
25 from
26 pg_proc as p
27 where
28 p.prokind = 'f'
29)
30select
31 f.oid as id,
32 n.nspname as schema,
33 f.proname as name,
34 l.lanname as language,
35 case
36 when l.lanname = 'internal' then ''
37 else f.prosrc
38 end as definition,
39 case
40 when l.lanname = 'internal' then f.prosrc
41 else pg_get_functiondef(f.oid)
42 end as complete_statement,
43 coalesce(f_args.args, '[]') as args,
44 pg_get_function_arguments(f.oid) as argument_types,
45 pg_get_function_identity_arguments(f.oid) as identity_argument_types,
46 f.prorettype as return_type_id,
47 pg_get_function_result(f.oid) as return_type,
48 nullif(rt.typrelid, 0) as return_type_relation_id,
49 f.proretset as is_set_returning_function,
50 case
51 when f.provolatile = 'i' then 'IMMUTABLE'
52 when f.provolatile = 's' then 'STABLE'
53 when f.provolatile = 'v' then 'VOLATILE'
54 end as behavior,
55 f.prosecdef as security_definer,
56 f_config.config_params as config_params
57from
58 functions f
59 left join pg_namespace n on f.pronamespace = n.oid
60 left join pg_language l on f.prolang = l.oid
61 left join pg_type rt on rt.oid = f.prorettype
62 left join (
63 select
64 oid,
65 jsonb_object_agg(param, value) filter (where param is not null) as config_params
66 from
67 (
68 select
69 oid,
70 (string_to_array(unnest(proconfig), '='))[1] as param,
71 (string_to_array(unnest(proconfig), '='))[2] as value
72 from
73 functions
74 ) as t
75 group by
76 oid
77 ) f_config on f_config.oid = f.oid
78 left join (
79 select
80 oid,
81 jsonb_agg(jsonb_build_object(
82 'mode', t2.mode,
83 'name', name,
84 'type_id', type_id,
85 -- Cast null into false boolean
86 'has_default', COALESCE(has_default, false)
87 )) as args
88 from
89 (
90 select
91 oid,
92 unnest(arg_modes) as mode,
93 unnest(arg_names) as name,
94 -- Coming from: coalesce(p.proallargtypes, p.proargtypes) postgres won't automatically assume
95 -- integer, we need to cast it to be properly parsed
96 unnest(arg_types)::int8 as type_id,
97 unnest(arg_has_defaults) as has_default
98 from
99 functions
100 ) as t1,
101 lateral (
102 select
103 case
104 when t1.mode = 'i' then 'in'
105 when t1.mode = 'o' then 'out'
106 when t1.mode = 'b' then 'inout'
107 when t1.mode = 'v' then 'variadic'
108 else 'table'
109 end as mode
110 ) as t2
111 group by
112 t1.oid
113 ) f_args on f_args.oid = f.oid
114`