-
-
Notifications
You must be signed in to change notification settings - Fork 200
Expand file tree
/
Copy pathfunctions.sql.ts
More file actions
155 lines (154 loc) · 4.48 KB
/
functions.sql.ts
File metadata and controls
155 lines (154 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import type { SQLQueryPropsWithSchemaFilterAndIdsFilter } from './common.js'
export const FUNCTIONS_SQL = (
props: SQLQueryPropsWithSchemaFilterAndIdsFilter & {
nameFilter?: string
args?: string[]
}
) => /* SQL */ `
-- CTE with sane arg_modes, arg_names, and arg_types.
-- All three are always of the same length.
-- All three include all args, including OUT and TABLE args.
with functions as (
select
p.*,
-- proargmodes is null when all arg modes are IN
coalesce(
p.proargmodes,
array_fill('i'::text, array[cardinality(coalesce(p.proallargtypes, p.proargtypes))])
) as arg_modes,
-- proargnames is null when all args are unnamed
coalesce(
p.proargnames,
array_fill(''::text, array[cardinality(coalesce(p.proallargtypes, p.proargtypes))])
) as arg_names,
-- proallargtypes is null when all arg modes are IN
coalesce(p.proallargtypes, p.proargtypes) as arg_types,
array_cat(
array_fill(false, array[pronargs - pronargdefaults]),
array_fill(true, array[pronargdefaults])) as arg_has_defaults
from
pg_proc as p
${props.schemaFilter ? `join pg_namespace n on p.pronamespace = n.oid` : ''}
where
${props.schemaFilter ? `n.nspname ${props.schemaFilter} AND` : ''}
${props.idsFilter ? `p.oid ${props.idsFilter} AND` : ''}
${props.nameFilter ? `p.proname ${props.nameFilter} AND` : ''}
${
props.args === undefined
? ''
: props.args.length > 0
? `p.proargtypes::text = ${
props.args.length
? `(
SELECT STRING_AGG(type_oid::text, ' ') FROM (
SELECT (
split_args.arr[
array_length(
split_args.arr,
1
)
]::regtype::oid
) AS type_oid FROM (
SELECT STRING_TO_ARRAY(
UNNEST(
ARRAY[${props.args}]
),
' '
) AS arr
) AS split_args
) args
)`
: "''"
} AND`
: ''
}
p.prokind = 'f'
)
select
f.oid::int8 as id,
n.nspname as schema,
f.proname as name,
l.lanname as language,
case
when l.lanname = 'internal' then ''
else f.prosrc
end as definition,
case
when l.lanname = 'internal' then f.prosrc
else pg_get_functiondef(f.oid)
end as complete_statement,
coalesce(f_args.args, '[]') as args,
pg_get_function_arguments(f.oid) as argument_types,
pg_get_function_identity_arguments(f.oid) as identity_argument_types,
f.prorettype::int8 as return_type_id,
pg_get_function_result(f.oid) as return_type,
nullif(rt.typrelid::int8, 0) as return_type_relation_id,
f.proretset as is_set_returning_function,
case
when f.proretset then nullif(f.prorows, 0)
else null
end as prorows,
case
when f.provolatile = 'i' then 'IMMUTABLE'
when f.provolatile = 's' then 'STABLE'
when f.provolatile = 'v' then 'VOLATILE'
end as behavior,
f.prosecdef as security_definer,
f_config.config_params as config_params
from
functions f
left join pg_namespace n on f.pronamespace = n.oid
left join pg_language l on f.prolang = l.oid
left join pg_type rt on rt.oid = f.prorettype
left join (
select
oid,
jsonb_object_agg(param, value) filter (where param is not null) as config_params
from
(
select
oid,
(string_to_array(unnest(proconfig), '='))[1] as param,
(string_to_array(unnest(proconfig), '='))[2] as value
from
functions
) as t
group by
oid
) f_config on f_config.oid = f.oid
left join (
select
oid,
jsonb_agg(jsonb_build_object(
'mode', t2.mode,
'name', name,
'type_id', type_id,
'has_default', has_default
)) as args
from
(
select
oid,
unnest(arg_modes) as mode,
unnest(arg_names) as name,
unnest(arg_types)::int8 as type_id,
unnest(arg_has_defaults) as has_default
from
functions
) as t1,
lateral (
select
case
when t1.mode = 'i' then 'in'
when t1.mode = 'o' then 'out'
when t1.mode = 'b' then 'inout'
when t1.mode = 'v' then 'variadic'
else 'table'
end as mode
) as t2
group by
t1.oid
) f_args on f_args.oid = f.oid
${props.limit ? `limit ${props.limit}` : ''}
${props.offset ? `offset ${props.offset}` : ''}
`