neon 8.4.5 → 8.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -9
- package/dist/_chunks/{env-4WGRW2nw.js → env-BNm69Qh8.js} +2 -5
- package/dist/commands/config.js +11 -28
- package/dist/commands/dev.js +93 -27
- package/dist/commands/env.js +2 -3
- package/dist/commands/init.js +1 -2
- package/dist/commands/link.js +1 -1
- package/dist/commands/manifest.js +1 -3
- package/dist/commands/subscribe.js +16 -16
- package/dist/credential_io.js +1 -2
- package/dist/dev/env.js +1 -2
- package/dist/dev/runtime.js +8 -0
- package/dist/env_file.js +9 -1
- package/dist/index.js +1 -1
- package/dist/init/auth.js +1 -4
- package/dist/init/choices.js +21 -7
- package/dist/init/copy.js +21 -7
- package/dist/init/run.js +25 -16
- package/dist/plugins/run.js +2 -1
- package/dist/psql/command/cmd_io.js +1 -2
- package/dist/psql/command/cmd_pipeline.js +1 -2
- package/dist/psql/core/common.js +1 -2
- package/dist/psql/core/startup.js +1 -2
- package/dist/psql/index.js +1 -2
- package/dist/psql/types/index.js +1 -2
- package/dist/skills/catalog.js +5 -0
- package/dist/utils/hooks.js +0 -2
- package/dist/utils/staging.js +1 -14
- package/{LICENSE → dist/vendor/postgres-meta/LICENSE} +0 -1
- package/dist/vendor/postgres-meta/constants.js +14 -0
- package/dist/vendor/postgres-meta/lib/PostgresMeta.js +49 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaColumnPrivileges.js +85 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaColumns.js +235 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaConfig.js +16 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaExtensions.js +79 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaForeignTables.js +81 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaFunctions.js +173 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaIndexes.js +42 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaMaterializedViews.js +84 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaPolicies.js +120 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaPublications.js +193 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaRelationships.js +87 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaRoles.js +203 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaSchemas.js +105 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaTablePrivileges.js +91 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaTables.js +183 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaTriggers.js +156 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaTypes.js +22 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaVersion.js +20 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaViews.js +83 -0
- package/dist/vendor/postgres-meta/lib/constants.js +8 -0
- package/dist/vendor/postgres-meta/lib/db.js +147 -0
- package/dist/vendor/postgres-meta/lib/generators.js +106 -0
- package/dist/vendor/postgres-meta/lib/helpers.js +26 -0
- package/dist/vendor/postgres-meta/lib/index.js +1 -0
- package/dist/vendor/postgres-meta/lib/sql/column_privileges.sql.js +154 -0
- package/dist/vendor/postgres-meta/lib/sql/columns.sql.js +123 -0
- package/dist/vendor/postgres-meta/lib/sql/common.js +1 -0
- package/dist/vendor/postgres-meta/lib/sql/config.sql.js +32 -0
- package/dist/vendor/postgres-meta/lib/sql/extensions.sql.js +20 -0
- package/dist/vendor/postgres-meta/lib/sql/foreign_tables.sql.js +20 -0
- package/dist/vendor/postgres-meta/lib/sql/functions.sql.js +141 -0
- package/dist/vendor/postgres-meta/lib/sql/indexes.sql.js +51 -0
- package/dist/vendor/postgres-meta/lib/sql/materialized_views.sql.js +21 -0
- package/dist/vendor/postgres-meta/lib/sql/policies.sql.js +53 -0
- package/dist/vendor/postgres-meta/lib/sql/publications.sql.js +46 -0
- package/dist/vendor/postgres-meta/lib/sql/roles.sql.js +40 -0
- package/dist/vendor/postgres-meta/lib/sql/schemas.sql.js +26 -0
- package/dist/vendor/postgres-meta/lib/sql/table.sql.js +109 -0
- package/dist/vendor/postgres-meta/lib/sql/table_privileges.sql.js +85 -0
- package/dist/vendor/postgres-meta/lib/sql/table_relationships.sql.js +52 -0
- package/dist/vendor/postgres-meta/lib/sql/triggers.sql.js +64 -0
- package/dist/vendor/postgres-meta/lib/sql/types.sql.js +65 -0
- package/dist/vendor/postgres-meta/lib/sql/version.sql.js +15 -0
- package/dist/vendor/postgres-meta/lib/sql/views.sql.js +22 -0
- package/dist/vendor/postgres-meta/lib/sql/views_key_dependencies.sql.js +198 -0
- package/dist/vendor/postgres-meta/lib/types.js +1 -0
- package/dist/vendor/postgres-meta/templates/typescript.js +608 -0
- package/package.json +12 -5
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/functions.sql.ts
|
|
2
|
+
const FUNCTIONS_SQL = (props) => `
|
|
3
|
+
-- CTE with sane arg_modes, arg_names, and arg_types.
|
|
4
|
+
-- All three are always of the same length.
|
|
5
|
+
-- All three include all args, including OUT and TABLE args.
|
|
6
|
+
with functions as (
|
|
7
|
+
select
|
|
8
|
+
p.*,
|
|
9
|
+
-- proargmodes is null when all arg modes are IN
|
|
10
|
+
coalesce(
|
|
11
|
+
p.proargmodes,
|
|
12
|
+
array_fill('i'::text, array[cardinality(coalesce(p.proallargtypes, p.proargtypes))])
|
|
13
|
+
) as arg_modes,
|
|
14
|
+
-- proargnames is null when all args are unnamed
|
|
15
|
+
coalesce(
|
|
16
|
+
p.proargnames,
|
|
17
|
+
array_fill(''::text, array[cardinality(coalesce(p.proallargtypes, p.proargtypes))])
|
|
18
|
+
) as arg_names,
|
|
19
|
+
-- proallargtypes is null when all arg modes are IN
|
|
20
|
+
coalesce(p.proallargtypes, p.proargtypes) as arg_types,
|
|
21
|
+
array_cat(
|
|
22
|
+
array_fill(false, array[pronargs - pronargdefaults]),
|
|
23
|
+
array_fill(true, array[pronargdefaults])) as arg_has_defaults
|
|
24
|
+
from
|
|
25
|
+
pg_proc as p
|
|
26
|
+
${props.schemaFilter ? `join pg_namespace n on p.pronamespace = n.oid` : ""}
|
|
27
|
+
where
|
|
28
|
+
${props.schemaFilter ? `n.nspname ${props.schemaFilter} AND` : ""}
|
|
29
|
+
${props.idsFilter ? `p.oid ${props.idsFilter} AND` : ""}
|
|
30
|
+
${props.nameFilter ? `p.proname ${props.nameFilter} AND` : ""}
|
|
31
|
+
${props.args === void 0 ? "" : props.args.length > 0 ? `p.proargtypes::text = ${props.args.length ? `(
|
|
32
|
+
SELECT STRING_AGG(type_oid::text, ' ') FROM (
|
|
33
|
+
SELECT (
|
|
34
|
+
split_args.arr[
|
|
35
|
+
array_length(
|
|
36
|
+
split_args.arr,
|
|
37
|
+
1
|
|
38
|
+
)
|
|
39
|
+
]::regtype::oid
|
|
40
|
+
) AS type_oid FROM (
|
|
41
|
+
SELECT STRING_TO_ARRAY(
|
|
42
|
+
UNNEST(
|
|
43
|
+
ARRAY[${props.args}]
|
|
44
|
+
),
|
|
45
|
+
' '
|
|
46
|
+
) AS arr
|
|
47
|
+
) AS split_args
|
|
48
|
+
) args
|
|
49
|
+
)` : "''"} AND` : ""}
|
|
50
|
+
p.prokind = 'f'
|
|
51
|
+
)
|
|
52
|
+
select
|
|
53
|
+
f.oid::int8 as id,
|
|
54
|
+
n.nspname as schema,
|
|
55
|
+
f.proname as name,
|
|
56
|
+
l.lanname as language,
|
|
57
|
+
case
|
|
58
|
+
when l.lanname = 'internal' then ''
|
|
59
|
+
else f.prosrc
|
|
60
|
+
end as definition,
|
|
61
|
+
case
|
|
62
|
+
when l.lanname = 'internal' then f.prosrc
|
|
63
|
+
else pg_get_functiondef(f.oid)
|
|
64
|
+
end as complete_statement,
|
|
65
|
+
coalesce(f_args.args, '[]') as args,
|
|
66
|
+
pg_get_function_arguments(f.oid) as argument_types,
|
|
67
|
+
pg_get_function_identity_arguments(f.oid) as identity_argument_types,
|
|
68
|
+
f.prorettype::int8 as return_type_id,
|
|
69
|
+
pg_get_function_result(f.oid) as return_type,
|
|
70
|
+
nullif(rt.typrelid::int8, 0) as return_type_relation_id,
|
|
71
|
+
f.proretset as is_set_returning_function,
|
|
72
|
+
case
|
|
73
|
+
when f.proretset then nullif(f.prorows, 0)
|
|
74
|
+
else null
|
|
75
|
+
end as prorows,
|
|
76
|
+
case
|
|
77
|
+
when f.provolatile = 'i' then 'IMMUTABLE'
|
|
78
|
+
when f.provolatile = 's' then 'STABLE'
|
|
79
|
+
when f.provolatile = 'v' then 'VOLATILE'
|
|
80
|
+
end as behavior,
|
|
81
|
+
f.prosecdef as security_definer,
|
|
82
|
+
f_config.config_params as config_params
|
|
83
|
+
from
|
|
84
|
+
functions f
|
|
85
|
+
left join pg_namespace n on f.pronamespace = n.oid
|
|
86
|
+
left join pg_language l on f.prolang = l.oid
|
|
87
|
+
left join pg_type rt on rt.oid = f.prorettype
|
|
88
|
+
left join (
|
|
89
|
+
select
|
|
90
|
+
oid,
|
|
91
|
+
jsonb_object_agg(param, value) filter (where param is not null) as config_params
|
|
92
|
+
from
|
|
93
|
+
(
|
|
94
|
+
select
|
|
95
|
+
oid,
|
|
96
|
+
(string_to_array(unnest(proconfig), '='))[1] as param,
|
|
97
|
+
(string_to_array(unnest(proconfig), '='))[2] as value
|
|
98
|
+
from
|
|
99
|
+
functions
|
|
100
|
+
) as t
|
|
101
|
+
group by
|
|
102
|
+
oid
|
|
103
|
+
) f_config on f_config.oid = f.oid
|
|
104
|
+
left join (
|
|
105
|
+
select
|
|
106
|
+
oid,
|
|
107
|
+
jsonb_agg(jsonb_build_object(
|
|
108
|
+
'mode', t2.mode,
|
|
109
|
+
'name', name,
|
|
110
|
+
'type_id', type_id,
|
|
111
|
+
'has_default', has_default
|
|
112
|
+
)) as args
|
|
113
|
+
from
|
|
114
|
+
(
|
|
115
|
+
select
|
|
116
|
+
oid,
|
|
117
|
+
unnest(arg_modes) as mode,
|
|
118
|
+
unnest(arg_names) as name,
|
|
119
|
+
unnest(arg_types)::int8 as type_id,
|
|
120
|
+
unnest(arg_has_defaults) as has_default
|
|
121
|
+
from
|
|
122
|
+
functions
|
|
123
|
+
) as t1,
|
|
124
|
+
lateral (
|
|
125
|
+
select
|
|
126
|
+
case
|
|
127
|
+
when t1.mode = 'i' then 'in'
|
|
128
|
+
when t1.mode = 'o' then 'out'
|
|
129
|
+
when t1.mode = 'b' then 'inout'
|
|
130
|
+
when t1.mode = 'v' then 'variadic'
|
|
131
|
+
else 'table'
|
|
132
|
+
end as mode
|
|
133
|
+
) as t2
|
|
134
|
+
group by
|
|
135
|
+
t1.oid
|
|
136
|
+
) f_args on f_args.oid = f.oid
|
|
137
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
138
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
139
|
+
`;
|
|
140
|
+
//#endregion
|
|
141
|
+
export { FUNCTIONS_SQL };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/indexes.sql.ts
|
|
2
|
+
const INDEXES_SQL = (props) => `
|
|
3
|
+
SELECT
|
|
4
|
+
idx.indexrelid::int8 AS id,
|
|
5
|
+
idx.indrelid::int8 AS table_id,
|
|
6
|
+
n.nspname AS schema,
|
|
7
|
+
idx.indnatts AS number_of_attributes,
|
|
8
|
+
idx.indnkeyatts AS number_of_key_attributes,
|
|
9
|
+
idx.indisunique AS is_unique,
|
|
10
|
+
idx.indisprimary AS is_primary,
|
|
11
|
+
idx.indisexclusion AS is_exclusion,
|
|
12
|
+
idx.indimmediate AS is_immediate,
|
|
13
|
+
idx.indisclustered AS is_clustered,
|
|
14
|
+
idx.indisvalid AS is_valid,
|
|
15
|
+
idx.indcheckxmin AS check_xmin,
|
|
16
|
+
idx.indisready AS is_ready,
|
|
17
|
+
idx.indislive AS is_live,
|
|
18
|
+
idx.indisreplident AS is_replica_identity,
|
|
19
|
+
idx.indkey::smallint[] AS key_attributes,
|
|
20
|
+
idx.indcollation::integer[] AS collation,
|
|
21
|
+
idx.indclass::integer[] AS class,
|
|
22
|
+
idx.indoption::smallint[] AS options,
|
|
23
|
+
idx.indpred AS index_predicate,
|
|
24
|
+
obj_description(idx.indexrelid, 'pg_class') AS comment,
|
|
25
|
+
ix.indexdef as index_definition,
|
|
26
|
+
am.amname AS access_method,
|
|
27
|
+
jsonb_agg(
|
|
28
|
+
jsonb_build_object(
|
|
29
|
+
'attribute_number', a.attnum,
|
|
30
|
+
'attribute_name', a.attname,
|
|
31
|
+
'data_type', format_type(a.atttypid, a.atttypmod)
|
|
32
|
+
)
|
|
33
|
+
ORDER BY a.attnum
|
|
34
|
+
) AS index_attributes
|
|
35
|
+
FROM
|
|
36
|
+
pg_index idx
|
|
37
|
+
JOIN pg_class c ON c.oid = idx.indexrelid
|
|
38
|
+
JOIN pg_namespace n ON c.relnamespace = n.oid
|
|
39
|
+
JOIN pg_am am ON c.relam = am.oid
|
|
40
|
+
JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = ANY(idx.indkey)
|
|
41
|
+
JOIN pg_indexes ix ON c.relname = ix.indexname
|
|
42
|
+
WHERE
|
|
43
|
+
${props.schemaFilter ? `n.nspname ${props.schemaFilter}` : "true"}
|
|
44
|
+
${props.idsFilter ? `AND idx.indexrelid ${props.idsFilter}` : ""}
|
|
45
|
+
GROUP BY
|
|
46
|
+
idx.indexrelid, idx.indrelid, n.nspname, idx.indnatts, idx.indnkeyatts, idx.indisunique, idx.indisprimary, idx.indisexclusion, idx.indimmediate, idx.indisclustered, idx.indisvalid, idx.indcheckxmin, idx.indisready, idx.indislive, idx.indisreplident, idx.indkey, idx.indcollation, idx.indclass, idx.indoption, idx.indexprs, idx.indpred, ix.indexdef, am.amname
|
|
47
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
48
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
49
|
+
`;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { INDEXES_SQL };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/materialized_views.sql.ts
|
|
2
|
+
const MATERIALIZED_VIEWS_SQL = (props) => `
|
|
3
|
+
select
|
|
4
|
+
c.oid::int8 as id,
|
|
5
|
+
n.nspname as schema,
|
|
6
|
+
c.relname as name,
|
|
7
|
+
c.relispopulated as is_populated,
|
|
8
|
+
obj_description(c.oid) as comment
|
|
9
|
+
from
|
|
10
|
+
pg_class c
|
|
11
|
+
join pg_namespace n on n.oid = c.relnamespace
|
|
12
|
+
where
|
|
13
|
+
${props.schemaFilter ? `n.nspname ${props.schemaFilter} AND` : ""}
|
|
14
|
+
${props.idsFilter ? `c.oid ${props.idsFilter} AND` : ""}
|
|
15
|
+
${props.materializedViewIdentifierFilter ? `(n.nspname || '.' || c.relname) ${props.materializedViewIdentifierFilter} AND` : ""}
|
|
16
|
+
c.relkind = 'm'
|
|
17
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
18
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
19
|
+
`;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { MATERIALIZED_VIEWS_SQL };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/policies.sql.ts
|
|
2
|
+
const POLICIES_SQL = (props) => `
|
|
3
|
+
SELECT
|
|
4
|
+
pol.oid :: int8 AS id,
|
|
5
|
+
n.nspname AS schema,
|
|
6
|
+
c.relname AS table,
|
|
7
|
+
c.oid :: int8 AS table_id,
|
|
8
|
+
pol.polname AS name,
|
|
9
|
+
CASE
|
|
10
|
+
WHEN pol.polpermissive THEN 'PERMISSIVE' :: text
|
|
11
|
+
ELSE 'RESTRICTIVE' :: text
|
|
12
|
+
END AS action,
|
|
13
|
+
CASE
|
|
14
|
+
WHEN pol.polroles = '{0}' :: oid [] THEN array_to_json(
|
|
15
|
+
string_to_array('public' :: text, '' :: text) :: name []
|
|
16
|
+
)
|
|
17
|
+
ELSE array_to_json(
|
|
18
|
+
ARRAY(
|
|
19
|
+
SELECT
|
|
20
|
+
pg_roles.rolname
|
|
21
|
+
FROM
|
|
22
|
+
pg_roles
|
|
23
|
+
WHERE
|
|
24
|
+
pg_roles.oid = ANY (pol.polroles)
|
|
25
|
+
ORDER BY
|
|
26
|
+
pg_roles.rolname
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
END AS roles,
|
|
30
|
+
CASE
|
|
31
|
+
pol.polcmd
|
|
32
|
+
WHEN 'r' :: "char" THEN 'SELECT' :: text
|
|
33
|
+
WHEN 'a' :: "char" THEN 'INSERT' :: text
|
|
34
|
+
WHEN 'w' :: "char" THEN 'UPDATE' :: text
|
|
35
|
+
WHEN 'd' :: "char" THEN 'DELETE' :: text
|
|
36
|
+
WHEN '*' :: "char" THEN 'ALL' :: text
|
|
37
|
+
ELSE NULL :: text
|
|
38
|
+
END AS command,
|
|
39
|
+
pg_get_expr(pol.polqual, pol.polrelid) AS definition,
|
|
40
|
+
pg_get_expr(pol.polwithcheck, pol.polrelid) AS check
|
|
41
|
+
FROM
|
|
42
|
+
pg_policy pol
|
|
43
|
+
JOIN pg_class c ON c.oid = pol.polrelid
|
|
44
|
+
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
45
|
+
WHERE
|
|
46
|
+
${props.schemaFilter ? `n.nspname ${props.schemaFilter}` : "true"}
|
|
47
|
+
${props.idsFilter ? `AND pol.oid ${props.idsFilter}` : ""}
|
|
48
|
+
${props.functionNameIdentifierFilter ? `AND (c.relname || '.' || pol.polname) ${props.functionNameIdentifierFilter}` : ""}
|
|
49
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
50
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
51
|
+
`;
|
|
52
|
+
//#endregion
|
|
53
|
+
export { POLICIES_SQL };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/publications.sql.ts
|
|
2
|
+
const PUBLICATIONS_SQL = (props) => `
|
|
3
|
+
SELECT
|
|
4
|
+
p.oid :: int8 AS id,
|
|
5
|
+
p.pubname AS name,
|
|
6
|
+
p.pubowner::regrole::text AS owner,
|
|
7
|
+
p.pubinsert AS publish_insert,
|
|
8
|
+
p.pubupdate AS publish_update,
|
|
9
|
+
p.pubdelete AS publish_delete,
|
|
10
|
+
p.pubtruncate AS publish_truncate,
|
|
11
|
+
CASE
|
|
12
|
+
WHEN p.puballtables THEN NULL
|
|
13
|
+
ELSE pr.tables
|
|
14
|
+
END AS tables
|
|
15
|
+
FROM
|
|
16
|
+
pg_catalog.pg_publication AS p
|
|
17
|
+
LEFT JOIN LATERAL (
|
|
18
|
+
SELECT
|
|
19
|
+
COALESCE(
|
|
20
|
+
array_agg(
|
|
21
|
+
json_build_object(
|
|
22
|
+
'id',
|
|
23
|
+
c.oid :: int8,
|
|
24
|
+
'name',
|
|
25
|
+
c.relname,
|
|
26
|
+
'schema',
|
|
27
|
+
nc.nspname
|
|
28
|
+
)
|
|
29
|
+
),
|
|
30
|
+
'{}'
|
|
31
|
+
) AS tables
|
|
32
|
+
FROM
|
|
33
|
+
pg_catalog.pg_publication_rel AS pr
|
|
34
|
+
JOIN pg_class AS c ON pr.prrelid = c.oid
|
|
35
|
+
join pg_namespace as nc on c.relnamespace = nc.oid
|
|
36
|
+
WHERE
|
|
37
|
+
pr.prpubid = p.oid
|
|
38
|
+
) AS pr ON 1 = 1
|
|
39
|
+
WHERE
|
|
40
|
+
${props.idsFilter ? `p.oid ${props.idsFilter}` : "true"}
|
|
41
|
+
${props.nameFilter ? `AND p.pubname ${props.nameFilter}` : ""}
|
|
42
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
43
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
44
|
+
`;
|
|
45
|
+
//#endregion
|
|
46
|
+
export { PUBLICATIONS_SQL };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/roles.sql.ts
|
|
2
|
+
const ROLES_SQL = (props) => `
|
|
3
|
+
-- TODO: Consider using pg_authid vs. pg_roles for unencrypted password field
|
|
4
|
+
SELECT
|
|
5
|
+
oid :: int8 AS id,
|
|
6
|
+
rolname AS name,
|
|
7
|
+
rolsuper AS is_superuser,
|
|
8
|
+
rolcreatedb AS can_create_db,
|
|
9
|
+
rolcreaterole AS can_create_role,
|
|
10
|
+
rolinherit AS inherit_role,
|
|
11
|
+
rolcanlogin AS can_login,
|
|
12
|
+
rolreplication AS is_replication_role,
|
|
13
|
+
rolbypassrls AS can_bypass_rls,
|
|
14
|
+
(
|
|
15
|
+
SELECT
|
|
16
|
+
COUNT(*)
|
|
17
|
+
FROM
|
|
18
|
+
pg_stat_activity
|
|
19
|
+
WHERE
|
|
20
|
+
pg_roles.rolname = pg_stat_activity.usename
|
|
21
|
+
) AS active_connections,
|
|
22
|
+
CASE WHEN rolconnlimit = -1 THEN current_setting('max_connections') :: int8
|
|
23
|
+
ELSE rolconnlimit
|
|
24
|
+
END AS connection_limit,
|
|
25
|
+
rolpassword AS password,
|
|
26
|
+
rolvaliduntil AS valid_until,
|
|
27
|
+
rolconfig AS config
|
|
28
|
+
FROM
|
|
29
|
+
pg_roles
|
|
30
|
+
WHERE
|
|
31
|
+
${props.idsFilter ? `oid ${props.idsFilter}` : "true"}
|
|
32
|
+
-- All default/predefined roles start with pg_: https://www.postgresql.org/docs/15/predefined-roles.html
|
|
33
|
+
-- The pg_ prefix is also reserved.
|
|
34
|
+
${!props.includeDefaultRoles ? `AND NOT pg_catalog.starts_with(rolname, 'pg_')` : ""}
|
|
35
|
+
${props.nameFilter ? `AND rolname ${props.nameFilter}` : ""}
|
|
36
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
37
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
38
|
+
`;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { ROLES_SQL };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/schemas.sql.ts
|
|
2
|
+
const SCHEMAS_SQL = (props) => `
|
|
3
|
+
-- Adapted from information_schema.schemata
|
|
4
|
+
select
|
|
5
|
+
n.oid::int8 as id,
|
|
6
|
+
n.nspname as name,
|
|
7
|
+
u.rolname as owner
|
|
8
|
+
from
|
|
9
|
+
pg_namespace n,
|
|
10
|
+
pg_roles u
|
|
11
|
+
where
|
|
12
|
+
n.nspowner = u.oid
|
|
13
|
+
${props.idsFilter ? `and n.oid ${props.idsFilter}` : ""}
|
|
14
|
+
${props.nameFilter ? `and n.nspname ${props.nameFilter}` : ""}
|
|
15
|
+
${!props.includeSystemSchemas ? `and not pg_catalog.starts_with(n.nspname, 'pg_')` : ""}
|
|
16
|
+
and (
|
|
17
|
+
pg_has_role(n.nspowner, 'USAGE')
|
|
18
|
+
or has_schema_privilege(n.oid, 'CREATE, USAGE')
|
|
19
|
+
)
|
|
20
|
+
and not pg_catalog.starts_with(n.nspname, 'pg_temp_')
|
|
21
|
+
and not pg_catalog.starts_with(n.nspname, 'pg_toast_temp_')
|
|
22
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
23
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
24
|
+
`;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { SCHEMAS_SQL };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/table.sql.ts
|
|
2
|
+
const TABLES_SQL = (props) => `
|
|
3
|
+
SELECT
|
|
4
|
+
c.oid :: int8 AS id,
|
|
5
|
+
nc.nspname AS schema,
|
|
6
|
+
c.relname AS name,
|
|
7
|
+
c.relrowsecurity AS rls_enabled,
|
|
8
|
+
c.relforcerowsecurity AS rls_forced,
|
|
9
|
+
CASE
|
|
10
|
+
WHEN c.relreplident = 'd' THEN 'DEFAULT'
|
|
11
|
+
WHEN c.relreplident = 'i' THEN 'INDEX'
|
|
12
|
+
WHEN c.relreplident = 'f' THEN 'FULL'
|
|
13
|
+
ELSE 'NOTHING'
|
|
14
|
+
END AS replica_identity,
|
|
15
|
+
pg_total_relation_size(format('%I.%I', nc.nspname, c.relname)) :: int8 AS bytes,
|
|
16
|
+
pg_size_pretty(
|
|
17
|
+
pg_total_relation_size(format('%I.%I', nc.nspname, c.relname))
|
|
18
|
+
) AS size,
|
|
19
|
+
pg_stat_get_live_tuples(c.oid) AS live_rows_estimate,
|
|
20
|
+
pg_stat_get_dead_tuples(c.oid) AS dead_rows_estimate,
|
|
21
|
+
obj_description(c.oid) AS comment,
|
|
22
|
+
coalesce(pk.primary_keys, '[]') as primary_keys,
|
|
23
|
+
coalesce(
|
|
24
|
+
jsonb_agg(relationships) filter (where relationships is not null),
|
|
25
|
+
'[]'
|
|
26
|
+
) as relationships
|
|
27
|
+
FROM
|
|
28
|
+
pg_namespace nc
|
|
29
|
+
JOIN pg_class c ON nc.oid = c.relnamespace
|
|
30
|
+
left join (
|
|
31
|
+
select
|
|
32
|
+
c.oid::int8 as table_id,
|
|
33
|
+
jsonb_agg(
|
|
34
|
+
jsonb_build_object(
|
|
35
|
+
'table_id', c.oid::int8,
|
|
36
|
+
'schema', n.nspname,
|
|
37
|
+
'table_name', c.relname,
|
|
38
|
+
'name', a.attname
|
|
39
|
+
)
|
|
40
|
+
order by array_position(i.indkey, a.attnum)
|
|
41
|
+
) as primary_keys
|
|
42
|
+
from
|
|
43
|
+
pg_index i
|
|
44
|
+
join pg_class c on i.indrelid = c.oid
|
|
45
|
+
join pg_namespace n on c.relnamespace = n.oid
|
|
46
|
+
join pg_attribute a on a.attrelid = c.oid and a.attnum = any(i.indkey)
|
|
47
|
+
where
|
|
48
|
+
${props.schemaFilter ? `n.nspname ${props.schemaFilter} AND` : ""}
|
|
49
|
+
${props.tableIdentifierFilter ? `n.nspname || '.' || c.relname ${props.tableIdentifierFilter} AND` : ""}
|
|
50
|
+
i.indisprimary
|
|
51
|
+
group by c.oid
|
|
52
|
+
) as pk
|
|
53
|
+
on pk.table_id = c.oid
|
|
54
|
+
left join (
|
|
55
|
+
select
|
|
56
|
+
c.oid :: int8 as id,
|
|
57
|
+
c.conname as constraint_name,
|
|
58
|
+
nsa.nspname as source_schema,
|
|
59
|
+
csa.relname as source_table_name,
|
|
60
|
+
sa.attname as source_column_name,
|
|
61
|
+
nta.nspname as target_table_schema,
|
|
62
|
+
cta.relname as target_table_name,
|
|
63
|
+
ta.attname as target_column_name
|
|
64
|
+
from
|
|
65
|
+
pg_constraint c
|
|
66
|
+
join (
|
|
67
|
+
pg_attribute sa
|
|
68
|
+
join pg_class csa on sa.attrelid = csa.oid
|
|
69
|
+
join pg_namespace nsa on csa.relnamespace = nsa.oid
|
|
70
|
+
) on sa.attrelid = c.conrelid and sa.attnum = any (c.conkey)
|
|
71
|
+
join (
|
|
72
|
+
pg_attribute ta
|
|
73
|
+
join pg_class cta on ta.attrelid = cta.oid
|
|
74
|
+
join pg_namespace nta on cta.relnamespace = nta.oid
|
|
75
|
+
) on ta.attrelid = c.confrelid and ta.attnum = any (c.confkey)
|
|
76
|
+
where
|
|
77
|
+
${props.schemaFilter ? `nsa.nspname ${props.schemaFilter} OR nta.nspname ${props.schemaFilter} AND` : ""}
|
|
78
|
+
${props.tableIdentifierFilter ? `(nsa.nspname || '.' || csa.relname) ${props.tableIdentifierFilter} OR (nta.nspname || '.' || cta.relname) ${props.tableIdentifierFilter} AND` : ""}
|
|
79
|
+
c.contype = 'f'
|
|
80
|
+
) as relationships
|
|
81
|
+
on (relationships.source_schema = nc.nspname and relationships.source_table_name = c.relname)
|
|
82
|
+
or (relationships.target_table_schema = nc.nspname and relationships.target_table_name = c.relname)
|
|
83
|
+
WHERE
|
|
84
|
+
${props.schemaFilter ? `nc.nspname ${props.schemaFilter} AND` : ""}
|
|
85
|
+
${props.idsFilter ? `c.oid ${props.idsFilter} AND` : ""}
|
|
86
|
+
${props.tableIdentifierFilter ? `nc.nspname || '.' || c.relname ${props.tableIdentifierFilter} AND` : ""}
|
|
87
|
+
c.relkind IN ('r', 'p')
|
|
88
|
+
AND NOT pg_is_other_temp_schema(nc.oid)
|
|
89
|
+
AND (
|
|
90
|
+
pg_has_role(c.relowner, 'USAGE')
|
|
91
|
+
OR has_table_privilege(
|
|
92
|
+
c.oid,
|
|
93
|
+
'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER'
|
|
94
|
+
)
|
|
95
|
+
OR has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES')
|
|
96
|
+
)
|
|
97
|
+
group by
|
|
98
|
+
c.oid,
|
|
99
|
+
c.relname,
|
|
100
|
+
c.relrowsecurity,
|
|
101
|
+
c.relforcerowsecurity,
|
|
102
|
+
c.relreplident,
|
|
103
|
+
nc.nspname,
|
|
104
|
+
pk.primary_keys
|
|
105
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
106
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
107
|
+
`;
|
|
108
|
+
//#endregion
|
|
109
|
+
export { TABLES_SQL };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/table_privileges.sql.ts
|
|
2
|
+
const TABLE_PRIVILEGES_SQL = (props) => `
|
|
3
|
+
-- Despite the name \`table_privileges\`, this includes other kinds of relations:
|
|
4
|
+
-- views, matviews, etc. "Relation privileges" just doesn't roll off the tongue.
|
|
5
|
+
--
|
|
6
|
+
-- For each relation, get its relacl in a jsonb format,
|
|
7
|
+
-- e.g.
|
|
8
|
+
--
|
|
9
|
+
-- '{postgres=arwdDxt/postgres}'
|
|
10
|
+
--
|
|
11
|
+
-- becomes
|
|
12
|
+
--
|
|
13
|
+
-- [
|
|
14
|
+
-- {
|
|
15
|
+
-- "grantee": "postgres",
|
|
16
|
+
-- "grantor": "postgres",
|
|
17
|
+
-- "is_grantable": false,
|
|
18
|
+
-- "privilege_type": "INSERT"
|
|
19
|
+
-- },
|
|
20
|
+
-- ...
|
|
21
|
+
-- ]
|
|
22
|
+
select
|
|
23
|
+
c.oid as relation_id,
|
|
24
|
+
nc.nspname as schema,
|
|
25
|
+
c.relname as name,
|
|
26
|
+
case
|
|
27
|
+
when c.relkind = 'r' then 'table'
|
|
28
|
+
when c.relkind = 'v' then 'view'
|
|
29
|
+
when c.relkind = 'm' then 'materialized_view'
|
|
30
|
+
when c.relkind = 'f' then 'foreign_table'
|
|
31
|
+
when c.relkind = 'p' then 'partitioned_table'
|
|
32
|
+
end as kind,
|
|
33
|
+
coalesce(
|
|
34
|
+
jsonb_agg(
|
|
35
|
+
jsonb_build_object(
|
|
36
|
+
'grantor', grantor.rolname,
|
|
37
|
+
'grantee', grantee.rolname,
|
|
38
|
+
'privilege_type', _priv.privilege_type,
|
|
39
|
+
'is_grantable', _priv.is_grantable
|
|
40
|
+
)
|
|
41
|
+
) filter (where _priv is not null),
|
|
42
|
+
'[]'
|
|
43
|
+
) as privileges
|
|
44
|
+
from pg_class c
|
|
45
|
+
join pg_namespace as nc
|
|
46
|
+
on nc.oid = c.relnamespace
|
|
47
|
+
left join lateral (
|
|
48
|
+
select grantor, grantee, privilege_type, is_grantable
|
|
49
|
+
from aclexplode(coalesce(c.relacl, acldefault('r', c.relowner)))
|
|
50
|
+
) as _priv on true
|
|
51
|
+
left join pg_roles as grantor
|
|
52
|
+
on grantor.oid = _priv.grantor
|
|
53
|
+
left join (
|
|
54
|
+
select
|
|
55
|
+
pg_roles.oid,
|
|
56
|
+
pg_roles.rolname
|
|
57
|
+
from pg_roles
|
|
58
|
+
union all
|
|
59
|
+
select
|
|
60
|
+
(0)::oid as oid, 'PUBLIC'
|
|
61
|
+
) as grantee (oid, rolname)
|
|
62
|
+
on grantee.oid = _priv.grantee
|
|
63
|
+
where c.relkind in ('r', 'v', 'm', 'f', 'p')
|
|
64
|
+
${props.schemaFilter ? `and nc.nspname ${props.schemaFilter}` : ""}
|
|
65
|
+
${props.idsFilter ? `and c.oid ${props.idsFilter}` : ""}
|
|
66
|
+
${props.nameIdentifierFilter ? `and (nc.nspname || '.' || c.relname) ${props.nameIdentifierFilter}` : ""}
|
|
67
|
+
and not pg_is_other_temp_schema(c.relnamespace)
|
|
68
|
+
and (
|
|
69
|
+
pg_has_role(c.relowner, 'USAGE')
|
|
70
|
+
or has_table_privilege(
|
|
71
|
+
c.oid,
|
|
72
|
+
'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER, MAINTAIN'
|
|
73
|
+
)
|
|
74
|
+
or has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES')
|
|
75
|
+
)
|
|
76
|
+
group by
|
|
77
|
+
c.oid,
|
|
78
|
+
nc.nspname,
|
|
79
|
+
c.relname,
|
|
80
|
+
c.relkind
|
|
81
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
82
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
83
|
+
`;
|
|
84
|
+
//#endregion
|
|
85
|
+
export { TABLE_PRIVILEGES_SQL };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/table_relationships.sql.ts
|
|
2
|
+
const TABLE_RELATIONSHIPS_SQL = (props) => `
|
|
3
|
+
-- Adapted from
|
|
4
|
+
-- https://github.com/PostgREST/postgrest/blob/f9f0f79fa914ac00c11fbf7f4c558e14821e67e2/src/PostgREST/SchemaCache.hs#L722
|
|
5
|
+
WITH
|
|
6
|
+
pks_uniques_cols AS (
|
|
7
|
+
SELECT
|
|
8
|
+
connamespace,
|
|
9
|
+
conrelid,
|
|
10
|
+
jsonb_agg(column_info.cols) as cols
|
|
11
|
+
FROM pg_constraint
|
|
12
|
+
JOIN lateral (
|
|
13
|
+
SELECT array_agg(cols.attname order by cols.attnum) as cols
|
|
14
|
+
FROM ( select unnest(conkey) as col) _
|
|
15
|
+
JOIN pg_attribute cols on cols.attrelid = conrelid and cols.attnum = col
|
|
16
|
+
) column_info ON TRUE
|
|
17
|
+
WHERE
|
|
18
|
+
contype IN ('p', 'u') and
|
|
19
|
+
connamespace::regnamespace::text <> 'pg_catalog'
|
|
20
|
+
${props.schemaFilter ? `and connamespace::regnamespace::text ${props.schemaFilter}` : ""}
|
|
21
|
+
GROUP BY connamespace, conrelid
|
|
22
|
+
)
|
|
23
|
+
SELECT
|
|
24
|
+
traint.conname AS foreign_key_name,
|
|
25
|
+
ns1.nspname AS schema,
|
|
26
|
+
tab.relname AS relation,
|
|
27
|
+
column_info.cols AS columns,
|
|
28
|
+
ns2.nspname AS referenced_schema,
|
|
29
|
+
other.relname AS referenced_relation,
|
|
30
|
+
column_info.refs AS referenced_columns,
|
|
31
|
+
(column_info.cols IN (SELECT * FROM jsonb_array_elements(pks_uqs.cols))) AS is_one_to_one
|
|
32
|
+
FROM pg_constraint traint
|
|
33
|
+
JOIN LATERAL (
|
|
34
|
+
SELECT
|
|
35
|
+
jsonb_agg(cols.attname order by ord) AS cols,
|
|
36
|
+
jsonb_agg(refs.attname order by ord) AS refs
|
|
37
|
+
FROM unnest(traint.conkey, traint.confkey) WITH ORDINALITY AS _(col, ref, ord)
|
|
38
|
+
JOIN pg_attribute cols ON cols.attrelid = traint.conrelid AND cols.attnum = col
|
|
39
|
+
JOIN pg_attribute refs ON refs.attrelid = traint.confrelid AND refs.attnum = ref
|
|
40
|
+
WHERE ${props.schemaFilter ? `traint.connamespace::regnamespace::text ${props.schemaFilter}` : "true"}
|
|
41
|
+
) AS column_info ON TRUE
|
|
42
|
+
JOIN pg_namespace ns1 ON ns1.oid = traint.connamespace
|
|
43
|
+
JOIN pg_class tab ON tab.oid = traint.conrelid
|
|
44
|
+
JOIN pg_class other ON other.oid = traint.confrelid
|
|
45
|
+
JOIN pg_namespace ns2 ON ns2.oid = other.relnamespace
|
|
46
|
+
LEFT JOIN pks_uniques_cols pks_uqs ON pks_uqs.connamespace = traint.connamespace AND pks_uqs.conrelid = traint.conrelid
|
|
47
|
+
WHERE traint.contype = 'f'
|
|
48
|
+
AND traint.conparentid = 0
|
|
49
|
+
${props.schemaFilter ? `and ns1.nspname ${props.schemaFilter}` : ""}
|
|
50
|
+
`;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { TABLE_RELATIONSHIPS_SQL };
|