neonctl 2.28.0 → 2.29.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 +2 -2
- package/dist/analytics.js +35 -33
- package/dist/api.js +34 -34
- package/dist/auth.js +50 -44
- package/dist/cli.js +2 -2
- package/dist/commands/auth.js +58 -52
- package/dist/commands/bootstrap.js +115 -157
- package/dist/commands/branches.js +154 -147
- package/dist/commands/bucket.js +124 -118
- package/dist/commands/checkout.js +49 -49
- package/dist/commands/config.js +212 -88
- package/dist/commands/connection_string.js +62 -62
- package/dist/commands/data_api.js +96 -96
- package/dist/commands/databases.js +23 -23
- package/dist/commands/deploy.js +12 -12
- package/dist/commands/dev.js +114 -114
- package/dist/commands/env.js +43 -43
- package/dist/commands/functions.js +97 -98
- package/dist/commands/index.js +26 -26
- package/dist/commands/init.js +23 -22
- package/dist/commands/ip_allow.js +29 -29
- package/dist/commands/link.js +223 -166
- package/dist/commands/neon_auth.js +381 -363
- package/dist/commands/operations.js +11 -11
- package/dist/commands/orgs.js +8 -8
- package/dist/commands/projects.js +101 -99
- package/dist/commands/psql.js +31 -31
- package/dist/commands/roles.js +21 -21
- package/dist/commands/schema_diff.js +23 -23
- package/dist/commands/set_context.js +17 -17
- package/dist/commands/status.js +17 -17
- package/dist/commands/user.js +5 -5
- package/dist/commands/vpc_endpoints.js +50 -50
- package/dist/config.js +7 -7
- package/dist/config_format.js +5 -5
- package/dist/context.js +23 -16
- package/dist/current_branch_fast_path.js +6 -6
- package/dist/dev/env.js +33 -33
- package/dist/dev/functions.js +4 -4
- package/dist/dev/inputs.js +6 -6
- package/dist/dev/runtime.js +25 -25
- package/dist/env.js +14 -14
- package/dist/env_file.js +13 -13
- package/dist/errors.js +19 -19
- package/dist/functions_api.js +10 -10
- package/dist/help.js +15 -15
- package/dist/index.js +94 -92
- package/dist/log.js +2 -2
- package/dist/pkg.js +5 -5
- package/dist/psql/cli.js +4 -2
- package/dist/psql/command/cmd_cond.js +61 -61
- package/dist/psql/command/cmd_connect.js +159 -154
- package/dist/psql/command/cmd_copy.js +107 -97
- package/dist/psql/command/cmd_describe.js +368 -363
- package/dist/psql/command/cmd_format.js +276 -263
- package/dist/psql/command/cmd_io.js +269 -263
- package/dist/psql/command/cmd_lo.js +74 -66
- package/dist/psql/command/cmd_meta.js +148 -148
- package/dist/psql/command/cmd_misc.js +17 -17
- package/dist/psql/command/cmd_pipeline.js +142 -135
- package/dist/psql/command/cmd_restrict.js +25 -25
- package/dist/psql/command/cmd_show.js +183 -168
- package/dist/psql/command/dispatch.js +26 -26
- package/dist/psql/command/shared.js +14 -14
- package/dist/psql/complete/filenames.js +16 -16
- package/dist/psql/complete/index.js +4 -4
- package/dist/psql/complete/matcher.js +33 -32
- package/dist/psql/complete/psqlVars.js +173 -173
- package/dist/psql/complete/queries.js +5 -3
- package/dist/psql/complete/rules.js +900 -863
- package/dist/psql/core/common.js +136 -133
- package/dist/psql/core/help.js +343 -343
- package/dist/psql/core/mainloop.js +160 -153
- package/dist/psql/core/prompt.js +126 -123
- package/dist/psql/core/settings.js +111 -111
- package/dist/psql/core/sqlHelp.js +150 -150
- package/dist/psql/core/startup.js +211 -205
- package/dist/psql/core/syncVars.js +14 -14
- package/dist/psql/core/variables.js +24 -24
- package/dist/psql/describe/formatters.js +302 -289
- package/dist/psql/describe/processNamePattern.js +28 -28
- package/dist/psql/describe/queries.js +656 -651
- package/dist/psql/index.js +436 -411
- package/dist/psql/io/history.js +36 -36
- package/dist/psql/io/input.js +15 -15
- package/dist/psql/io/lineEditor/buffer.js +27 -25
- package/dist/psql/io/lineEditor/complete.js +15 -15
- package/dist/psql/io/lineEditor/filename.js +22 -22
- package/dist/psql/io/lineEditor/index.js +65 -62
- package/dist/psql/io/lineEditor/keymap.js +325 -318
- package/dist/psql/io/lineEditor/vt100.js +60 -60
- package/dist/psql/io/pgpass.js +18 -18
- package/dist/psql/io/pgservice.js +14 -14
- package/dist/psql/io/psqlrc.js +46 -46
- package/dist/psql/print/aligned.js +175 -166
- package/dist/psql/print/asciidoc.js +51 -51
- package/dist/psql/print/crosstab.js +34 -31
- package/dist/psql/print/csv.js +25 -22
- package/dist/psql/print/html.js +54 -54
- package/dist/psql/print/json.js +12 -12
- package/dist/psql/print/latex.js +118 -118
- package/dist/psql/print/pager.js +28 -26
- package/dist/psql/print/troff.js +48 -48
- package/dist/psql/print/unaligned.js +15 -14
- package/dist/psql/print/units.js +17 -17
- package/dist/psql/scanner/slash.js +48 -46
- package/dist/psql/scanner/sql.js +88 -84
- package/dist/psql/scanner/stringutils.js +21 -17
- package/dist/psql/types/index.js +7 -7
- package/dist/psql/types/scanner.js +8 -8
- package/dist/psql/wire/connection.js +341 -327
- package/dist/psql/wire/copy.js +7 -7
- package/dist/psql/wire/pipeline.js +26 -24
- package/dist/psql/wire/protocol.js +102 -102
- package/dist/psql/wire/sasl.js +62 -62
- package/dist/psql/wire/tls.js +79 -73
- package/dist/storage_api.js +15 -15
- package/dist/test_utils/fixtures.js +34 -31
- package/dist/test_utils/oauth_server.js +5 -5
- package/dist/utils/api_enums.js +13 -13
- package/dist/utils/branch_notice.js +5 -5
- package/dist/utils/branch_picker.js +26 -26
- package/dist/utils/compute_units.js +4 -4
- package/dist/utils/enrichers.js +20 -15
- package/dist/utils/esbuild.js +28 -28
- package/dist/utils/formats.js +1 -1
- package/dist/utils/middlewares.js +3 -3
- package/dist/utils/package_manager.js +68 -0
- package/dist/utils/point_in_time.js +12 -12
- package/dist/utils/psql.js +30 -30
- package/dist/utils/string.js +2 -2
- package/dist/utils/ui.js +9 -9
- package/dist/utils/zip.js +1 -1
- package/dist/writer.js +17 -17
- package/package.json +6 -7
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* branches in the C source collapse into TS conditional concatenation gated
|
|
18
18
|
* on `serverVersion`.
|
|
19
19
|
*/
|
|
20
|
-
import {
|
|
20
|
+
import { PG_9_5, PG_9_6, PG_10, PG_11, PG_12, PG_13, PG_14, PG_15, PG_16, PG_17, PG_18, serverAtLeast, serverLess, } from "./versionGate.js";
|
|
21
21
|
/* ------------------------------------------------------------------ */
|
|
22
22
|
/* Shared helpers */
|
|
23
23
|
/* ------------------------------------------------------------------ */
|
|
@@ -41,7 +41,7 @@ const patternStub = (hasWhere, schemaCol, nameCol) => {
|
|
|
41
41
|
// TODO(WP-20): real pattern matching via processSQLNamePattern port.
|
|
42
42
|
void schemaCol;
|
|
43
43
|
void nameCol;
|
|
44
|
-
const join = hasWhere ?
|
|
44
|
+
const join = hasWhere ? " AND " : "WHERE ";
|
|
45
45
|
return `${join}true /* TODO(WP-20): pattern matching */\n`;
|
|
46
46
|
};
|
|
47
47
|
/**
|
|
@@ -66,32 +66,32 @@ const params = () => [];
|
|
|
66
66
|
/* ------------------------------------------------------------------ */
|
|
67
67
|
export const describeAggregates = (opts) => {
|
|
68
68
|
const { showSystem, pattern, serverVersion } = opts;
|
|
69
|
-
let sql =
|
|
69
|
+
let sql = "";
|
|
70
70
|
sql +=
|
|
71
71
|
'SELECT n.nspname as "Schema",\n' +
|
|
72
72
|
' p.proname AS "Name",\n' +
|
|
73
73
|
' pg_catalog.format_type(p.prorettype, NULL) AS "Result data type",\n' +
|
|
74
|
-
|
|
74
|
+
" CASE WHEN p.pronargs = 0\n" +
|
|
75
75
|
" THEN CAST('*' AS pg_catalog.text)\n" +
|
|
76
|
-
|
|
76
|
+
" ELSE pg_catalog.pg_get_function_arguments(p.oid)\n" +
|
|
77
77
|
' END AS "Argument data types",\n' +
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
" pg_catalog.obj_description(p.oid, 'pg_proc') as \"Description\"\n" +
|
|
79
|
+
"FROM pg_catalog.pg_proc p\n" +
|
|
80
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n";
|
|
81
81
|
sql += serverAtLeast(serverVersion, PG_11)
|
|
82
82
|
? "WHERE p.prokind = 'a'\n"
|
|
83
|
-
:
|
|
83
|
+
: "WHERE p.proisagg\n";
|
|
84
84
|
if (!showSystem && pattern === undefined) {
|
|
85
85
|
sql +=
|
|
86
86
|
" AND n.nspname <> 'pg_catalog'\n" +
|
|
87
87
|
" AND n.nspname <> 'information_schema'\n";
|
|
88
88
|
}
|
|
89
|
-
sql += patternStub(true,
|
|
90
|
-
sql += orderBy(
|
|
89
|
+
sql += patternStub(true, "n.nspname", "p.proname");
|
|
90
|
+
sql += orderBy("1, 2, 4");
|
|
91
91
|
return {
|
|
92
92
|
sql,
|
|
93
93
|
params: params(),
|
|
94
|
-
description:
|
|
94
|
+
description: "List of aggregate functions",
|
|
95
95
|
};
|
|
96
96
|
};
|
|
97
97
|
/* ------------------------------------------------------------------ */
|
|
@@ -101,9 +101,9 @@ export const describeAccessMethods = (opts) => {
|
|
|
101
101
|
const { verbose, serverVersion } = opts;
|
|
102
102
|
if (serverLess(serverVersion, 9, 6)) {
|
|
103
103
|
return {
|
|
104
|
-
sql:
|
|
104
|
+
sql: "/* server < 9.6 does not support access methods */ SELECT 1 WHERE false;",
|
|
105
105
|
params: [],
|
|
106
|
-
description:
|
|
106
|
+
description: "List of access methods",
|
|
107
107
|
};
|
|
108
108
|
}
|
|
109
109
|
let sql = 'SELECT amname AS "Name",\n' +
|
|
@@ -111,12 +111,12 @@ export const describeAccessMethods = (opts) => {
|
|
|
111
111
|
if (verbose) {
|
|
112
112
|
sql +=
|
|
113
113
|
',\n amhandler AS "Handler",\n' +
|
|
114
|
-
|
|
114
|
+
" pg_catalog.obj_description(oid, 'pg_am') AS \"Description\"";
|
|
115
115
|
}
|
|
116
|
-
sql +=
|
|
117
|
-
sql += patternStub(false, undefined,
|
|
118
|
-
sql += orderBy(
|
|
119
|
-
return { sql, params: params(), description:
|
|
116
|
+
sql += "\nFROM pg_catalog.pg_am\n";
|
|
117
|
+
sql += patternStub(false, undefined, "amname");
|
|
118
|
+
sql += orderBy("1");
|
|
119
|
+
return { sql, params: params(), description: "List of access methods" };
|
|
120
120
|
};
|
|
121
121
|
/* ------------------------------------------------------------------ */
|
|
122
122
|
/* \db — describeTablespaces */
|
|
@@ -127,26 +127,26 @@ export const describeTablespaces = (opts) => {
|
|
|
127
127
|
' pg_catalog.pg_get_userbyid(spcowner) AS "Owner",\n' +
|
|
128
128
|
' pg_catalog.pg_tablespace_location(oid) AS "Location"';
|
|
129
129
|
if (verbose) {
|
|
130
|
-
sql +=
|
|
130
|
+
sql += ",\n " + aclColumn("spcacl");
|
|
131
131
|
sql +=
|
|
132
132
|
',\n spcoptions AS "Options",\n' +
|
|
133
133
|
' pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS "Size",\n' +
|
|
134
|
-
|
|
134
|
+
" pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"Description\"";
|
|
135
135
|
}
|
|
136
|
-
sql +=
|
|
137
|
-
sql += patternStub(false, undefined,
|
|
138
|
-
sql += orderBy(
|
|
139
|
-
return { sql, params: params(), description:
|
|
136
|
+
sql += "\nFROM pg_catalog.pg_tablespace\n";
|
|
137
|
+
sql += patternStub(false, undefined, "spcname");
|
|
138
|
+
sql += orderBy("1");
|
|
139
|
+
return { sql, params: params(), description: "List of tablespaces" };
|
|
140
140
|
};
|
|
141
141
|
export const describeFunctions = (opts) => {
|
|
142
142
|
const { verbose, showSystem, pattern, serverVersion } = opts;
|
|
143
|
-
const functypes = opts.functypes ??
|
|
143
|
+
const functypes = opts.functypes ?? "";
|
|
144
144
|
const argPatterns = opts.argPatterns ?? [];
|
|
145
|
-
let showAgg = functypes.includes(
|
|
146
|
-
let showNorm = functypes.includes(
|
|
147
|
-
let showProc = functypes.includes(
|
|
148
|
-
let showTrig = functypes.includes(
|
|
149
|
-
let showWin = functypes.includes(
|
|
145
|
+
let showAgg = functypes.includes("a");
|
|
146
|
+
let showNorm = functypes.includes("n");
|
|
147
|
+
let showProc = functypes.includes("p");
|
|
148
|
+
let showTrig = functypes.includes("t");
|
|
149
|
+
let showWin = functypes.includes("w");
|
|
150
150
|
if (!showAgg && !showNorm && !showProc && !showTrig && !showWin) {
|
|
151
151
|
showAgg = showNorm = showTrig = showWin = true;
|
|
152
152
|
if (serverAtLeast(serverVersion, PG_11))
|
|
@@ -157,7 +157,7 @@ export const describeFunctions = (opts) => {
|
|
|
157
157
|
sql +=
|
|
158
158
|
' pg_catalog.pg_get_function_result(p.oid) as "Result data type",\n' +
|
|
159
159
|
' pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",\n' +
|
|
160
|
-
|
|
160
|
+
" CASE p.prokind\n" +
|
|
161
161
|
" WHEN 'a' THEN 'agg'\n" +
|
|
162
162
|
" WHEN 'w' THEN 'window'\n" +
|
|
163
163
|
" WHEN 'p' THEN 'proc'\n" +
|
|
@@ -168,7 +168,7 @@ export const describeFunctions = (opts) => {
|
|
|
168
168
|
sql +=
|
|
169
169
|
' pg_catalog.pg_get_function_result(p.oid) as "Result data type",\n' +
|
|
170
170
|
' pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",\n' +
|
|
171
|
-
|
|
171
|
+
" CASE\n" +
|
|
172
172
|
" WHEN p.proisagg THEN 'agg'\n" +
|
|
173
173
|
" WHEN p.proiswindow THEN 'window'\n" +
|
|
174
174
|
" WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'\n" +
|
|
@@ -177,14 +177,14 @@ export const describeFunctions = (opts) => {
|
|
|
177
177
|
}
|
|
178
178
|
if (verbose) {
|
|
179
179
|
sql +=
|
|
180
|
-
|
|
180
|
+
",\n CASE\n" +
|
|
181
181
|
" WHEN p.provolatile = 'i' THEN 'immutable'\n" +
|
|
182
182
|
" WHEN p.provolatile = 's' THEN 'stable'\n" +
|
|
183
183
|
" WHEN p.provolatile = 'v' THEN 'volatile'\n" +
|
|
184
184
|
' END as "Volatility"';
|
|
185
185
|
if (serverAtLeast(serverVersion, PG_9_6)) {
|
|
186
186
|
sql +=
|
|
187
|
-
|
|
187
|
+
",\n CASE\n" +
|
|
188
188
|
" WHEN p.proparallel = 'r' THEN 'restricted'\n" +
|
|
189
189
|
" WHEN p.proparallel = 's' THEN 'safe'\n" +
|
|
190
190
|
" WHEN p.proparallel = 'u' THEN 'unsafe'\n" +
|
|
@@ -200,15 +200,15 @@ export const describeFunctions = (opts) => {
|
|
|
200
200
|
sql +=
|
|
201
201
|
",\n CASE WHEN p.proleakproof THEN 'yes' ELSE 'no' END as \"Leakproof?\"";
|
|
202
202
|
}
|
|
203
|
-
sql +=
|
|
203
|
+
sql += ",\n " + aclColumn("p.proacl");
|
|
204
204
|
sql +=
|
|
205
205
|
',\n l.lanname as "Language"' +
|
|
206
206
|
",\n CASE WHEN l.lanname IN ('internal', 'c') THEN p.prosrc END as \"Internal name\"" +
|
|
207
|
-
|
|
207
|
+
",\n pg_catalog.obj_description(p.oid, 'pg_proc') as \"Description\"";
|
|
208
208
|
}
|
|
209
209
|
sql +=
|
|
210
|
-
|
|
211
|
-
|
|
210
|
+
"\nFROM pg_catalog.pg_proc p" +
|
|
211
|
+
"\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n";
|
|
212
212
|
// Upstream emits the per-argument joins *before* the verbose-language
|
|
213
213
|
// join so that all `t<i>`/`nt<i>` tables exist by the time the WHERE
|
|
214
214
|
// pulls in per-arg conditions. See describe.c::describeFunctions.
|
|
@@ -218,42 +218,44 @@ export const describeFunctions = (opts) => {
|
|
|
218
218
|
` LEFT JOIN pg_catalog.pg_namespace nt${i} ON nt${i}.oid = t${i}.typnamespace\n`;
|
|
219
219
|
}
|
|
220
220
|
if (verbose) {
|
|
221
|
-
sql +=
|
|
221
|
+
sql += " LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang\n";
|
|
222
222
|
}
|
|
223
223
|
let hasWhere = false;
|
|
224
224
|
const allTypes = showAgg && showNorm && showProc && showTrig && showWin;
|
|
225
225
|
if (!allTypes && showNorm) {
|
|
226
226
|
if (!showAgg) {
|
|
227
|
-
sql += hasWhere ?
|
|
227
|
+
sql += hasWhere ? " AND " : "WHERE ";
|
|
228
228
|
hasWhere = true;
|
|
229
229
|
sql += serverAtLeast(serverVersion, PG_11)
|
|
230
230
|
? "p.prokind <> 'a'\n"
|
|
231
|
-
:
|
|
231
|
+
: "NOT p.proisagg\n";
|
|
232
232
|
}
|
|
233
233
|
if (!showProc && serverAtLeast(serverVersion, PG_11)) {
|
|
234
|
-
sql += hasWhere ?
|
|
234
|
+
sql += hasWhere ? " AND " : "WHERE ";
|
|
235
235
|
hasWhere = true;
|
|
236
236
|
sql += "p.prokind <> 'p'\n";
|
|
237
237
|
}
|
|
238
238
|
if (!showTrig) {
|
|
239
|
-
sql += hasWhere ?
|
|
239
|
+
sql += hasWhere ? " AND " : "WHERE ";
|
|
240
240
|
hasWhere = true;
|
|
241
241
|
sql += "p.prorettype <> 'pg_catalog.trigger'::pg_catalog.regtype\n";
|
|
242
242
|
}
|
|
243
243
|
if (!showWin) {
|
|
244
|
-
sql += hasWhere ?
|
|
244
|
+
sql += hasWhere ? " AND " : "WHERE ";
|
|
245
245
|
hasWhere = true;
|
|
246
246
|
sql += serverAtLeast(serverVersion, PG_11)
|
|
247
247
|
? "p.prokind <> 'w'\n"
|
|
248
|
-
:
|
|
248
|
+
: "NOT p.proiswindow\n";
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
else if (!allTypes) {
|
|
252
|
-
sql +=
|
|
252
|
+
sql += "WHERE (\n ";
|
|
253
253
|
hasWhere = true;
|
|
254
254
|
const parts = [];
|
|
255
255
|
if (showAgg) {
|
|
256
|
-
parts.push(serverAtLeast(serverVersion, PG_11)
|
|
256
|
+
parts.push(serverAtLeast(serverVersion, PG_11)
|
|
257
|
+
? "p.prokind = 'a'"
|
|
258
|
+
: "p.proisagg");
|
|
257
259
|
}
|
|
258
260
|
if (showTrig) {
|
|
259
261
|
parts.push("p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype");
|
|
@@ -263,18 +265,18 @@ export const describeFunctions = (opts) => {
|
|
|
263
265
|
if (showWin) {
|
|
264
266
|
parts.push(serverAtLeast(serverVersion, PG_11)
|
|
265
267
|
? "p.prokind = 'w'"
|
|
266
|
-
:
|
|
268
|
+
: "p.proiswindow");
|
|
267
269
|
}
|
|
268
|
-
sql += parts.join(
|
|
270
|
+
sql += parts.join("\n OR ") + "\n )\n";
|
|
269
271
|
}
|
|
270
|
-
sql += patternStub(hasWhere,
|
|
272
|
+
sql += patternStub(hasWhere, "n.nspname", "p.proname");
|
|
271
273
|
// Upstream's per-argument filter loop. `-` means "no type in this
|
|
272
274
|
// slot" (function has fewer args); anything else is a type-name
|
|
273
275
|
// pattern matched against typname/format_type — same shape as `\dT`.
|
|
274
276
|
// Each slot emits a uniquely tagged placeholder so cmd_describe.ts
|
|
275
277
|
// can splice in the appropriate per-arg conditions.
|
|
276
278
|
for (let i = 0; i < argPatterns.length; i++) {
|
|
277
|
-
if (argPatterns[i] ===
|
|
279
|
+
if (argPatterns[i] === "-") {
|
|
278
280
|
sql += ` AND t${i}.typname IS NULL\n`;
|
|
279
281
|
}
|
|
280
282
|
else {
|
|
@@ -286,8 +288,8 @@ export const describeFunctions = (opts) => {
|
|
|
286
288
|
" AND n.nspname <> 'pg_catalog'\n" +
|
|
287
289
|
" AND n.nspname <> 'information_schema'\n";
|
|
288
290
|
}
|
|
289
|
-
sql += orderBy(
|
|
290
|
-
return { sql, params: params(), description:
|
|
291
|
+
sql += orderBy("1, 2, 4");
|
|
292
|
+
return { sql, params: params(), description: "List of functions" };
|
|
291
293
|
};
|
|
292
294
|
/* ------------------------------------------------------------------ */
|
|
293
295
|
/* \dT — describeTypes */
|
|
@@ -298,44 +300,45 @@ export const describeTypes = (opts) => {
|
|
|
298
300
|
if (verbose) {
|
|
299
301
|
sql +=
|
|
300
302
|
' t.typname AS "Internal name",\n' +
|
|
301
|
-
|
|
303
|
+
" CASE WHEN t.typrelid != 0\n" +
|
|
302
304
|
" THEN CAST('tuple' AS pg_catalog.text)\n" +
|
|
303
|
-
|
|
305
|
+
" WHEN t.typlen < 0\n" +
|
|
304
306
|
" THEN CAST('var' AS pg_catalog.text)\n" +
|
|
305
|
-
|
|
307
|
+
" ELSE CAST(t.typlen AS pg_catalog.text)\n" +
|
|
306
308
|
' END AS "Size",\n' +
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
309
|
+
" pg_catalog.array_to_string(\n" +
|
|
310
|
+
" ARRAY(\n" +
|
|
311
|
+
" SELECT e.enumlabel\n" +
|
|
312
|
+
" FROM pg_catalog.pg_enum e\n" +
|
|
313
|
+
" WHERE e.enumtypid = t.oid\n" +
|
|
314
|
+
" ORDER BY e.enumsortorder\n" +
|
|
315
|
+
" ),\n" +
|
|
314
316
|
" E'\\n'\n" +
|
|
315
317
|
' ) AS "Elements",\n' +
|
|
316
318
|
' pg_catalog.pg_get_userbyid(t.typowner) AS "Owner",\n ' +
|
|
317
|
-
aclColumn(
|
|
318
|
-
|
|
319
|
+
aclColumn("t.typacl") +
|
|
320
|
+
",\n ";
|
|
319
321
|
}
|
|
320
|
-
sql += ' pg_catalog.obj_description(t.oid, \'pg_type\') as "Description"\n';
|
|
321
322
|
sql +=
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
323
|
+
" pg_catalog.obj_description(t.oid, 'pg_type') as \"Description\"\n";
|
|
324
|
+
sql +=
|
|
325
|
+
"FROM pg_catalog.pg_type t\n" +
|
|
326
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n";
|
|
327
|
+
sql += "WHERE (t.typrelid = 0 ";
|
|
325
328
|
sql +=
|
|
326
329
|
"OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid))\n";
|
|
327
|
-
if (!pattern?.includes(
|
|
330
|
+
if (!pattern?.includes("[]")) {
|
|
328
331
|
sql +=
|
|
329
|
-
|
|
332
|
+
" AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n";
|
|
330
333
|
}
|
|
331
334
|
if (!showSystem && pattern === undefined) {
|
|
332
335
|
sql +=
|
|
333
336
|
" AND n.nspname <> 'pg_catalog'\n" +
|
|
334
337
|
" AND n.nspname <> 'information_schema'\n";
|
|
335
338
|
}
|
|
336
|
-
sql += patternStub(true,
|
|
337
|
-
sql += orderBy(
|
|
338
|
-
return { sql, params: params(), description:
|
|
339
|
+
sql += patternStub(true, "n.nspname", "t.typname");
|
|
340
|
+
sql += orderBy("1, 2");
|
|
341
|
+
return { sql, params: params(), description: "List of data types" };
|
|
339
342
|
};
|
|
340
343
|
export const describeOperators = (opts) => {
|
|
341
344
|
const { verbose, showSystem, pattern, serverVersion } = opts;
|
|
@@ -345,8 +348,8 @@ export const describeOperators = (opts) => {
|
|
|
345
348
|
argPatterns = argPatterns.slice(0, 2);
|
|
346
349
|
let sql = 'SELECT n.nspname as "Schema",\n' +
|
|
347
350
|
' o.oprname AS "Name",\n' +
|
|
348
|
-
|
|
349
|
-
|
|
351
|
+
" CASE WHEN o.oprkind='l' THEN NULL ELSE pg_catalog.format_type(o.oprleft, NULL) END AS \"Left arg type\",\n" +
|
|
352
|
+
" CASE WHEN o.oprkind='r' THEN NULL ELSE pg_catalog.format_type(o.oprright, NULL) END AS \"Right arg type\",\n" +
|
|
350
353
|
' pg_catalog.format_type(o.oprresult, NULL) AS "Result type",\n';
|
|
351
354
|
if (verbose) {
|
|
352
355
|
sql += ' o.oprcode AS "Function",\n';
|
|
@@ -359,28 +362,28 @@ export const describeOperators = (opts) => {
|
|
|
359
362
|
}
|
|
360
363
|
sql +=
|
|
361
364
|
" coalesce(pg_catalog.obj_description(o.oid, 'pg_operator'),\n" +
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
+
" pg_catalog.obj_description(o.oprcode, 'pg_proc')) AS \"Description\"\n" +
|
|
366
|
+
"FROM pg_catalog.pg_operator o\n" +
|
|
367
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n";
|
|
365
368
|
// Upstream emits arg-type joins before the verbose `pg_proc` join.
|
|
366
369
|
// With one arg pattern: only join the right-hand side (oprright);
|
|
367
370
|
// with two: both oprleft/oprright. Tag indices match the join name
|
|
368
371
|
// so `t0/nt0` correspond to the first arg pattern slot.
|
|
369
372
|
if (argPatterns.length === 1) {
|
|
370
373
|
sql +=
|
|
371
|
-
|
|
372
|
-
|
|
374
|
+
" LEFT JOIN pg_catalog.pg_type t0 ON t0.oid = o.oprright\n" +
|
|
375
|
+
" LEFT JOIN pg_catalog.pg_namespace nt0 ON nt0.oid = t0.typnamespace\n";
|
|
373
376
|
}
|
|
374
377
|
else if (argPatterns.length >= 2) {
|
|
375
378
|
sql +=
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
379
|
+
" LEFT JOIN pg_catalog.pg_type t0 ON t0.oid = o.oprleft\n" +
|
|
380
|
+
" LEFT JOIN pg_catalog.pg_namespace nt0 ON nt0.oid = t0.typnamespace\n" +
|
|
381
|
+
" LEFT JOIN pg_catalog.pg_type t1 ON t1.oid = o.oprright\n" +
|
|
382
|
+
" LEFT JOIN pg_catalog.pg_namespace nt1 ON nt1.oid = t1.typnamespace\n";
|
|
380
383
|
}
|
|
381
384
|
if (verbose && serverAtLeast(serverVersion, PG_18)) {
|
|
382
385
|
// Only joined when we need proleakproof from pg_proc (PG 18+).
|
|
383
|
-
sql +=
|
|
386
|
+
sql += " LEFT JOIN pg_catalog.pg_proc p ON p.oid = o.oprcode\n";
|
|
384
387
|
}
|
|
385
388
|
let hasWhere = false;
|
|
386
389
|
if (!showSystem && pattern === undefined) {
|
|
@@ -388,43 +391,43 @@ export const describeOperators = (opts) => {
|
|
|
388
391
|
"WHERE n.nspname <> 'pg_catalog'\n AND n.nspname <> 'information_schema'\n";
|
|
389
392
|
hasWhere = true;
|
|
390
393
|
}
|
|
391
|
-
sql += patternStub(hasWhere,
|
|
394
|
+
sql += patternStub(hasWhere, "n.nspname", "o.oprname");
|
|
392
395
|
// With a single arg pattern, upstream additionally constrains the
|
|
393
396
|
// operator to be unary-right (oprleft = 0) so unrelated binary
|
|
394
397
|
// operators don't leak through the `t0` join.
|
|
395
398
|
if (argPatterns.length === 1) {
|
|
396
|
-
sql +=
|
|
399
|
+
sql += " AND o.oprleft = 0\n";
|
|
397
400
|
}
|
|
398
401
|
for (let i = 0; i < argPatterns.length; i++) {
|
|
399
|
-
if (argPatterns[i] ===
|
|
402
|
+
if (argPatterns[i] === "-") {
|
|
400
403
|
sql += ` AND t${i}.typname IS NULL\n`;
|
|
401
404
|
}
|
|
402
405
|
else {
|
|
403
406
|
sql += ` AND ${argPatternStub(i)}\n`;
|
|
404
407
|
}
|
|
405
408
|
}
|
|
406
|
-
sql += orderBy(
|
|
407
|
-
return { sql, params: params(), description:
|
|
409
|
+
sql += orderBy("1, 2, 3, 4");
|
|
410
|
+
return { sql, params: params(), description: "List of operators" };
|
|
408
411
|
};
|
|
409
412
|
/* ------------------------------------------------------------------ */
|
|
410
413
|
/* \l / \list — listAllDbs */
|
|
411
414
|
/* ------------------------------------------------------------------ */
|
|
412
415
|
export const listAllDbs = (opts) => {
|
|
413
416
|
const { verbose, serverVersion } = opts;
|
|
414
|
-
let sql =
|
|
417
|
+
let sql = "SELECT\n" +
|
|
415
418
|
' d.datname as "Name",\n' +
|
|
416
419
|
' pg_catalog.pg_get_userbyid(d.datdba) as "Owner",\n' +
|
|
417
420
|
' pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding",\n';
|
|
418
421
|
if (serverAtLeast(serverVersion, PG_15)) {
|
|
419
422
|
sql +=
|
|
420
|
-
|
|
423
|
+
" CASE d.datlocprovider" +
|
|
421
424
|
" WHEN 'b' THEN 'builtin'" +
|
|
422
425
|
" WHEN 'c' THEN 'libc'" +
|
|
423
426
|
" WHEN 'i' THEN 'icu'" +
|
|
424
427
|
' END AS "Locale Provider",\n';
|
|
425
428
|
}
|
|
426
429
|
else {
|
|
427
|
-
sql +=
|
|
430
|
+
sql += " 'libc' AS \"Locale Provider\",\n";
|
|
428
431
|
}
|
|
429
432
|
sql += ' d.datcollate as "Collate",\n d.datctype as "Ctype",\n';
|
|
430
433
|
if (serverAtLeast(serverVersion, PG_17)) {
|
|
@@ -442,25 +445,25 @@ export const listAllDbs = (opts) => {
|
|
|
442
445
|
else {
|
|
443
446
|
sql += ' NULL as "ICU Rules",\n';
|
|
444
447
|
}
|
|
445
|
-
sql +=
|
|
448
|
+
sql += " " + aclColumn("d.datacl");
|
|
446
449
|
if (verbose) {
|
|
447
450
|
sql +=
|
|
448
451
|
",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" +
|
|
449
|
-
|
|
452
|
+
" THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" +
|
|
450
453
|
" ELSE 'No Access'\n" +
|
|
451
454
|
' END as "Size"' +
|
|
452
455
|
',\n t.spcname as "Tablespace"' +
|
|
453
|
-
|
|
456
|
+
",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"Description\"";
|
|
454
457
|
}
|
|
455
|
-
sql +=
|
|
458
|
+
sql += "\nFROM pg_catalog.pg_database d\n";
|
|
456
459
|
if (verbose) {
|
|
457
|
-
sql +=
|
|
460
|
+
sql += " JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n";
|
|
458
461
|
}
|
|
459
462
|
if (opts.pattern !== undefined) {
|
|
460
|
-
sql += patternStub(false, undefined,
|
|
463
|
+
sql += patternStub(false, undefined, "d.datname");
|
|
461
464
|
}
|
|
462
|
-
sql += orderBy(
|
|
463
|
-
return { sql, params: params(), description:
|
|
465
|
+
sql += orderBy("1");
|
|
466
|
+
return { sql, params: params(), description: "List of databases" };
|
|
464
467
|
};
|
|
465
468
|
/* ------------------------------------------------------------------ */
|
|
466
469
|
/* \dp / \z — permissionsList */
|
|
@@ -469,7 +472,7 @@ export const permissionsList = (opts) => {
|
|
|
469
472
|
const { showSystem, pattern, serverVersion } = opts;
|
|
470
473
|
let sql = 'SELECT n.nspname as "Schema",\n' +
|
|
471
474
|
' c.relname as "Name",\n' +
|
|
472
|
-
|
|
475
|
+
" CASE c.relkind" +
|
|
473
476
|
" WHEN 'r' THEN 'table'" +
|
|
474
477
|
" WHEN 'v' THEN 'view'" +
|
|
475
478
|
" WHEN 'm' THEN 'materialized view'" +
|
|
@@ -477,51 +480,51 @@ export const permissionsList = (opts) => {
|
|
|
477
480
|
" WHEN 'f' THEN 'foreign table'" +
|
|
478
481
|
" WHEN 'p' THEN 'partitioned table'" +
|
|
479
482
|
' END as "Type",\n ';
|
|
480
|
-
sql += aclColumn(
|
|
483
|
+
sql += aclColumn("c.relacl");
|
|
481
484
|
sql +=
|
|
482
|
-
|
|
485
|
+
",\n pg_catalog.array_to_string(ARRAY(\n" +
|
|
483
486
|
" SELECT attname || E':\\n ' || pg_catalog.array_to_string(attacl, E'\\n ')\n" +
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
+
" FROM pg_catalog.pg_attribute a\n" +
|
|
488
|
+
" WHERE attrelid = c.oid AND NOT attisdropped AND attacl IS NOT NULL\n" +
|
|
489
|
+
" ), E'\\n') AS \"Column privileges\"";
|
|
487
490
|
if (serverAtLeast(serverVersion, PG_10)) {
|
|
488
491
|
sql +=
|
|
489
|
-
|
|
490
|
-
|
|
492
|
+
",\n pg_catalog.array_to_string(ARRAY(\n" +
|
|
493
|
+
" SELECT polname\n" +
|
|
491
494
|
" || CASE WHEN NOT polpermissive THEN E' (RESTRICTIVE)' ELSE '' END\n" +
|
|
492
495
|
" || CASE WHEN polcmd != '*' THEN E' (' || polcmd::pg_catalog.text || E'):' ELSE E':' END\n" +
|
|
493
496
|
" || CASE WHEN polqual IS NOT NULL THEN E'\\n (u): ' || pg_catalog.pg_get_expr(polqual, polrelid) ELSE E'' END\n" +
|
|
494
497
|
" || CASE WHEN polwithcheck IS NOT NULL THEN E'\\n (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid) ELSE E'' END\n" +
|
|
495
498
|
" || CASE WHEN polroles <> '{0}' THEN E'\\n to: ' || pg_catalog.array_to_string(\n" +
|
|
496
|
-
|
|
499
|
+
" ARRAY(SELECT rolname FROM pg_catalog.pg_roles WHERE oid = ANY (polroles) ORDER BY 1)\n" +
|
|
497
500
|
" , E', ') ELSE E'' END\n" +
|
|
498
|
-
|
|
499
|
-
|
|
501
|
+
" FROM pg_catalog.pg_policy pol\n" +
|
|
502
|
+
" WHERE polrelid = c.oid), E'\\n') AS \"Policies\"";
|
|
500
503
|
}
|
|
501
504
|
else if (serverAtLeast(serverVersion, PG_9_5)) {
|
|
502
505
|
sql +=
|
|
503
|
-
|
|
504
|
-
|
|
506
|
+
",\n pg_catalog.array_to_string(ARRAY(\n" +
|
|
507
|
+
" SELECT polname\n" +
|
|
505
508
|
" || CASE WHEN polcmd != '*' THEN E' (' || polcmd::pg_catalog.text || E'):' ELSE E':' END\n" +
|
|
506
509
|
" || CASE WHEN polqual IS NOT NULL THEN E'\\n (u): ' || pg_catalog.pg_get_expr(polqual, polrelid) ELSE E'' END\n" +
|
|
507
510
|
" || CASE WHEN polwithcheck IS NOT NULL THEN E'\\n (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid) ELSE E'' END\n" +
|
|
508
511
|
" || CASE WHEN polroles <> '{0}' THEN E'\\n to: ' || pg_catalog.array_to_string(\n" +
|
|
509
|
-
|
|
512
|
+
" ARRAY(SELECT rolname FROM pg_catalog.pg_roles WHERE oid = ANY (polroles) ORDER BY 1)\n" +
|
|
510
513
|
" , E', ') ELSE E'' END\n" +
|
|
511
|
-
|
|
512
|
-
|
|
514
|
+
" FROM pg_catalog.pg_policy pol\n" +
|
|
515
|
+
" WHERE polrelid = c.oid), E'\\n') AS \"Policies\"";
|
|
513
516
|
}
|
|
514
517
|
sql +=
|
|
515
|
-
|
|
516
|
-
|
|
518
|
+
"\nFROM pg_catalog.pg_class c\n" +
|
|
519
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" +
|
|
517
520
|
"WHERE c.relkind IN ('r','v','m','S','f','p')\n";
|
|
518
521
|
if (!showSystem && pattern === undefined) {
|
|
519
522
|
sql +=
|
|
520
523
|
" AND n.nspname <> 'pg_catalog'\n AND n.nspname <> 'information_schema'\n";
|
|
521
524
|
}
|
|
522
|
-
sql += patternStub(true,
|
|
523
|
-
sql += orderBy(
|
|
524
|
-
return { sql, params: params(), description:
|
|
525
|
+
sql += patternStub(true, "n.nspname", "c.relname");
|
|
526
|
+
sql += orderBy("1, 2");
|
|
527
|
+
return { sql, params: params(), description: "Access privileges" };
|
|
525
528
|
};
|
|
526
529
|
/* ------------------------------------------------------------------ */
|
|
527
530
|
/* \ddp — listDefaultACLs */
|
|
@@ -533,7 +536,7 @@ export const listDefaultACLs = (opts) => {
|
|
|
533
536
|
// there — but to mirror upstream `\ddp` output, we gate it.
|
|
534
537
|
let sql = 'SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS "Owner",\n' +
|
|
535
538
|
' n.nspname AS "Schema",\n' +
|
|
536
|
-
|
|
539
|
+
" CASE d.defaclobjtype" +
|
|
537
540
|
" WHEN 'r' THEN 'table'" +
|
|
538
541
|
" WHEN 'S' THEN 'sequence'" +
|
|
539
542
|
" WHEN 'f' THEN 'function'" +
|
|
@@ -543,16 +546,16 @@ export const listDefaultACLs = (opts) => {
|
|
|
543
546
|
sql += " WHEN 'L' THEN 'large object'";
|
|
544
547
|
}
|
|
545
548
|
sql += ' END AS "Type",\n ';
|
|
546
|
-
sql += aclColumn(
|
|
549
|
+
sql += aclColumn("d.defaclacl");
|
|
547
550
|
sql +=
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
sql += patternStub(false,
|
|
551
|
-
sql += orderBy(
|
|
551
|
+
"\nFROM pg_catalog.pg_default_acl d\n" +
|
|
552
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.defaclnamespace\n";
|
|
553
|
+
sql += patternStub(false, "n.nspname", "pg_catalog.pg_get_userbyid(d.defaclrole)");
|
|
554
|
+
sql += orderBy("1, 2, 3");
|
|
552
555
|
return {
|
|
553
556
|
sql,
|
|
554
557
|
params: params(),
|
|
555
|
-
description:
|
|
558
|
+
description: "Default access privileges",
|
|
556
559
|
};
|
|
557
560
|
};
|
|
558
561
|
/* ------------------------------------------------------------------ */
|
|
@@ -564,70 +567,70 @@ export const objectDescription = (opts) => {
|
|
|
564
567
|
` /* ${objLabel} */ `
|
|
565
568
|
: `WHERE true /* ${objLabel} */ `;
|
|
566
569
|
let sql = 'SELECT DISTINCT tt.nspname AS "Schema", tt.name AS "Name", tt.object AS "Object", d.description AS "Description"\n' +
|
|
567
|
-
|
|
570
|
+
"FROM (\n";
|
|
568
571
|
sql +=
|
|
569
|
-
|
|
570
|
-
|
|
572
|
+
" SELECT pgc.oid as oid, pgc.tableoid AS tableoid, n.nspname as nspname,\n" +
|
|
573
|
+
" CAST(pgc.conname AS pg_catalog.text) as name," +
|
|
571
574
|
" CAST('table constraint' AS pg_catalog.text) as object\n" +
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
sysPart(
|
|
576
|
-
|
|
575
|
+
" FROM pg_catalog.pg_constraint pgc\n" +
|
|
576
|
+
" JOIN pg_catalog.pg_class c ON c.oid = pgc.conrelid\n" +
|
|
577
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" +
|
|
578
|
+
sysPart("table constraint") +
|
|
579
|
+
"\n";
|
|
577
580
|
sql +=
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
+
"UNION ALL\n" +
|
|
582
|
+
" SELECT pgc.oid, pgc.tableoid, n.nspname,\n" +
|
|
583
|
+
" CAST(pgc.conname AS pg_catalog.text)," +
|
|
581
584
|
" CAST('domain constraint' AS pg_catalog.text)\n" +
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
sysPart(
|
|
586
|
-
|
|
585
|
+
" FROM pg_catalog.pg_constraint pgc\n" +
|
|
586
|
+
" JOIN pg_catalog.pg_type t ON t.oid = pgc.contypid\n" +
|
|
587
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n" +
|
|
588
|
+
sysPart("domain constraint") +
|
|
589
|
+
"\n";
|
|
587
590
|
sql +=
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
+
"UNION ALL\n" +
|
|
592
|
+
" SELECT o.oid, o.tableoid, n.nspname,\n" +
|
|
593
|
+
" CAST(o.opcname AS pg_catalog.text)," +
|
|
591
594
|
" CAST('operator class' AS pg_catalog.text)\n" +
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
sysPart(
|
|
596
|
-
|
|
595
|
+
" FROM pg_catalog.pg_opclass o\n" +
|
|
596
|
+
" JOIN pg_catalog.pg_am am ON o.opcmethod = am.oid\n" +
|
|
597
|
+
" JOIN pg_catalog.pg_namespace n ON n.oid = o.opcnamespace\n" +
|
|
598
|
+
sysPart("operator class") +
|
|
599
|
+
"\n";
|
|
597
600
|
sql +=
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
+
"UNION ALL\n" +
|
|
602
|
+
" SELECT opf.oid, opf.tableoid, n.nspname,\n" +
|
|
603
|
+
" CAST(opf.opfname AS pg_catalog.text)," +
|
|
601
604
|
" CAST('operator family' AS pg_catalog.text)\n" +
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
sysPart(
|
|
606
|
-
|
|
605
|
+
" FROM pg_catalog.pg_opfamily opf\n" +
|
|
606
|
+
" JOIN pg_catalog.pg_am am ON opf.opfmethod = am.oid\n" +
|
|
607
|
+
" JOIN pg_catalog.pg_namespace n ON opf.opfnamespace = n.oid\n" +
|
|
608
|
+
sysPart("operator family") +
|
|
609
|
+
"\n";
|
|
607
610
|
sql +=
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
+
"UNION ALL\n" +
|
|
612
|
+
" SELECT r.oid, r.tableoid, n.nspname,\n" +
|
|
613
|
+
" CAST(r.rulename AS pg_catalog.text)," +
|
|
611
614
|
" CAST('rule' AS pg_catalog.text)\n" +
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
+
" FROM pg_catalog.pg_rewrite r\n" +
|
|
616
|
+
" JOIN pg_catalog.pg_class c ON c.oid = r.ev_class\n" +
|
|
617
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" +
|
|
615
618
|
" WHERE r.rulename != '_RETURN'\n";
|
|
616
619
|
sql +=
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
+
"UNION ALL\n" +
|
|
621
|
+
" SELECT t.oid, t.tableoid, n.nspname,\n" +
|
|
622
|
+
" CAST(t.tgname AS pg_catalog.text)," +
|
|
620
623
|
" CAST('trigger' AS pg_catalog.text)\n" +
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
sysPart(
|
|
625
|
-
|
|
624
|
+
" FROM pg_catalog.pg_trigger t\n" +
|
|
625
|
+
" JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid\n" +
|
|
626
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" +
|
|
627
|
+
sysPart("trigger") +
|
|
628
|
+
"\n";
|
|
626
629
|
sql +=
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
sql += orderBy(
|
|
630
|
-
return { sql, params: params(), description:
|
|
630
|
+
") AS tt\n" +
|
|
631
|
+
" JOIN pg_catalog.pg_description d ON (tt.oid = d.objoid AND tt.tableoid = d.classoid AND d.objsubid = 0)\n";
|
|
632
|
+
sql += orderBy("1, 2, 3");
|
|
633
|
+
return { sql, params: params(), description: "Object descriptions" };
|
|
631
634
|
};
|
|
632
635
|
/* ------------------------------------------------------------------ */
|
|
633
636
|
/* \d (no args / \d <name>) — describeTableDetails */
|
|
@@ -643,7 +646,7 @@ export const describeTableDetails = (opts) => {
|
|
|
643
646
|
// matches `\dt+ [pat]` shape.
|
|
644
647
|
let sql = 'SELECT n.nspname as "Schema",\n' +
|
|
645
648
|
' c.relname as "Name",\n' +
|
|
646
|
-
|
|
649
|
+
" CASE c.relkind" +
|
|
647
650
|
" WHEN 'r' THEN 'table'" +
|
|
648
651
|
" WHEN 'v' THEN 'view'" +
|
|
649
652
|
" WHEN 'm' THEN 'materialized view'" +
|
|
@@ -657,7 +660,7 @@ export const describeTableDetails = (opts) => {
|
|
|
657
660
|
' pg_catalog.pg_get_userbyid(c.relowner) as "Owner"';
|
|
658
661
|
if (verbose) {
|
|
659
662
|
sql +=
|
|
660
|
-
|
|
663
|
+
",\n CASE c.relpersistence" +
|
|
661
664
|
" WHEN 'p' THEN 'permanent'" +
|
|
662
665
|
" WHEN 't' THEN 'temporary'" +
|
|
663
666
|
" WHEN 'u' THEN 'unlogged'" +
|
|
@@ -667,13 +670,13 @@ export const describeTableDetails = (opts) => {
|
|
|
667
670
|
}
|
|
668
671
|
sql +=
|
|
669
672
|
',\n pg_catalog.pg_size_pretty(pg_catalog.pg_total_relation_size(c.oid)) as "Size"' +
|
|
670
|
-
|
|
673
|
+
",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"Description\"";
|
|
671
674
|
}
|
|
672
675
|
sql +=
|
|
673
|
-
|
|
674
|
-
|
|
676
|
+
"\nFROM pg_catalog.pg_class c" +
|
|
677
|
+
"\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace";
|
|
675
678
|
if (verbose && !hideTableam && serverAtLeast(serverVersion, PG_12)) {
|
|
676
|
-
sql +=
|
|
679
|
+
sql += "\n LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam";
|
|
677
680
|
}
|
|
678
681
|
sql += "\nWHERE c.relkind IN ('r','p','v','m','S','f','')\n";
|
|
679
682
|
if (!showSystem && pattern === undefined) {
|
|
@@ -682,12 +685,12 @@ export const describeTableDetails = (opts) => {
|
|
|
682
685
|
" AND n.nspname !~ '^pg_toast'\n" +
|
|
683
686
|
" AND n.nspname <> 'information_schema'\n";
|
|
684
687
|
}
|
|
685
|
-
sql += patternStub(true,
|
|
686
|
-
sql += orderBy(
|
|
688
|
+
sql += patternStub(true, "n.nspname", "c.relname");
|
|
689
|
+
sql += orderBy("1,2");
|
|
687
690
|
return {
|
|
688
691
|
sql,
|
|
689
692
|
params: params(),
|
|
690
|
-
description:
|
|
693
|
+
description: "List of relations",
|
|
691
694
|
};
|
|
692
695
|
};
|
|
693
696
|
/* ------------------------------------------------------------------ */
|
|
@@ -721,55 +724,55 @@ export const describeRoles = (opts) => {
|
|
|
721
724
|
attrParts.push("CASE WHEN r.rolbypassrls THEN 'Bypass RLS' END");
|
|
722
725
|
}
|
|
723
726
|
// `rolconnlimit = -1` means unlimited; only render when >= 0.
|
|
724
|
-
attrParts.push(
|
|
727
|
+
attrParts.push("CASE WHEN r.rolconnlimit >= 0 THEN" +
|
|
725
728
|
" pg_catalog.format('%s connection%s', r.rolconnlimit," +
|
|
726
729
|
" CASE WHEN r.rolconnlimit = 1 THEN '' ELSE 's' END) END");
|
|
727
730
|
// `rolvaliduntil` rendered with upstream's `Password valid until <ts>`.
|
|
728
|
-
attrParts.push(
|
|
731
|
+
attrParts.push("CASE WHEN r.rolvaliduntil IS NOT NULL THEN" +
|
|
729
732
|
" pg_catalog.format('Password valid until %s', r.rolvaliduntil) END");
|
|
730
|
-
const attrValues = attrParts.map((p) => `(${p})`).join(
|
|
733
|
+
const attrValues = attrParts.map((p) => `(${p})`).join(",\n ");
|
|
731
734
|
let sql = 'SELECT r.rolname AS "Role name",\n' +
|
|
732
|
-
|
|
733
|
-
|
|
735
|
+
" pg_catalog.array_to_string(ARRAY(\n" +
|
|
736
|
+
" SELECT a FROM (VALUES\n" +
|
|
734
737
|
` ${attrValues}\n` +
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
+
" ) AS x(a)\n" +
|
|
739
|
+
" WHERE a IS NOT NULL\n" +
|
|
740
|
+
" ), ', ') AS \"Attributes\"";
|
|
738
741
|
if (verbose) {
|
|
739
742
|
sql +=
|
|
740
|
-
|
|
743
|
+
",\n pg_catalog.shobj_description(r.oid, 'pg_authid') AS \"Description\"";
|
|
741
744
|
}
|
|
742
|
-
sql +=
|
|
745
|
+
sql += "\nFROM pg_catalog.pg_roles r\n";
|
|
743
746
|
let hasWhere = false;
|
|
744
747
|
if (!showSystem && pattern === undefined) {
|
|
745
748
|
sql += "WHERE r.rolname !~ '^pg_'\n";
|
|
746
749
|
hasWhere = true;
|
|
747
750
|
}
|
|
748
|
-
sql += patternStub(hasWhere, undefined,
|
|
749
|
-
sql += orderBy(
|
|
750
|
-
return { sql, params: params(), description:
|
|
751
|
+
sql += patternStub(hasWhere, undefined, "r.rolname");
|
|
752
|
+
sql += orderBy("1");
|
|
753
|
+
return { sql, params: params(), description: "List of roles" };
|
|
751
754
|
};
|
|
752
755
|
export const listDbRoleSettings = (opts) => {
|
|
753
756
|
let sql = 'SELECT rolname AS "Role", datname AS "Database",\n' +
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
757
|
+
"pg_catalog.array_to_string(setconfig, E'\\n') AS \"Settings\"\n" +
|
|
758
|
+
"FROM pg_catalog.pg_db_role_setting s\n" +
|
|
759
|
+
"LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase\n" +
|
|
760
|
+
"LEFT JOIN pg_catalog.pg_roles r ON r.oid = setrole\n";
|
|
758
761
|
let hasWhere = false;
|
|
759
762
|
if (opts.pattern !== undefined) {
|
|
760
|
-
sql += patternStub(hasWhere, undefined,
|
|
763
|
+
sql += patternStub(hasWhere, undefined, "r.rolname");
|
|
761
764
|
hasWhere = true;
|
|
762
765
|
}
|
|
763
766
|
if (opts.pattern2 !== undefined) {
|
|
764
|
-
sql += patternStub(hasWhere, undefined,
|
|
767
|
+
sql += patternStub(hasWhere, undefined, "d.datname");
|
|
765
768
|
}
|
|
766
|
-
sql += orderBy(
|
|
769
|
+
sql += orderBy("1, 2");
|
|
767
770
|
const ps = [];
|
|
768
771
|
if (opts.pattern !== undefined)
|
|
769
772
|
ps.push(opts.pattern);
|
|
770
773
|
if (opts.pattern2 !== undefined)
|
|
771
774
|
ps.push(opts.pattern2);
|
|
772
|
-
return { sql, params: ps, description:
|
|
775
|
+
return { sql, params: ps, description: "List of settings" };
|
|
773
776
|
};
|
|
774
777
|
/* ------------------------------------------------------------------ */
|
|
775
778
|
/* \drg — describeRoleGrants */
|
|
@@ -792,29 +795,29 @@ export const describeRoleGrants = (opts) => {
|
|
|
792
795
|
}
|
|
793
796
|
sql += ' ) AS "Options",\n g.rolname AS "Grantor"\n';
|
|
794
797
|
sql +=
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
798
|
+
"FROM pg_catalog.pg_roles m\n" +
|
|
799
|
+
" JOIN pg_catalog.pg_auth_members pam ON (pam.member = m.oid)\n" +
|
|
800
|
+
" LEFT JOIN pg_catalog.pg_roles r ON (pam.roleid = r.oid)\n" +
|
|
801
|
+
" LEFT JOIN pg_catalog.pg_roles g ON (pam.grantor = g.oid)\n";
|
|
799
802
|
let hasWhere = false;
|
|
800
803
|
if (!showSystem && pattern === undefined) {
|
|
801
804
|
sql += "WHERE m.rolname !~ '^pg_'\n";
|
|
802
805
|
hasWhere = true;
|
|
803
806
|
}
|
|
804
|
-
sql += patternStub(hasWhere, undefined,
|
|
805
|
-
sql += orderBy(
|
|
806
|
-
return { sql, params: params(), description:
|
|
807
|
+
sql += patternStub(hasWhere, undefined, "m.rolname");
|
|
808
|
+
sql += orderBy("1, 2, 4");
|
|
809
|
+
return { sql, params: params(), description: "List of role grants" };
|
|
807
810
|
};
|
|
808
811
|
export const listTables = (opts) => {
|
|
809
812
|
const { verbose, showSystem, pattern, serverVersion } = opts;
|
|
810
813
|
const hideTableam = opts.hideTableam ?? false;
|
|
811
|
-
const tt = opts.tabtypes ??
|
|
812
|
-
let showTables = tt.includes(
|
|
813
|
-
const showIndexes = tt.includes(
|
|
814
|
-
let showViews = tt.includes(
|
|
815
|
-
let showMatViews = tt.includes(
|
|
816
|
-
let showSeq = tt.includes(
|
|
817
|
-
let showForeign = tt.includes(
|
|
814
|
+
const tt = opts.tabtypes ?? "";
|
|
815
|
+
let showTables = tt.includes("t");
|
|
816
|
+
const showIndexes = tt.includes("i");
|
|
817
|
+
let showViews = tt.includes("v");
|
|
818
|
+
let showMatViews = tt.includes("m");
|
|
819
|
+
let showSeq = tt.includes("s");
|
|
820
|
+
let showForeign = tt.includes("E");
|
|
818
821
|
const ntypes = +showTables +
|
|
819
822
|
+showIndexes +
|
|
820
823
|
+showViews +
|
|
@@ -826,7 +829,7 @@ export const listTables = (opts) => {
|
|
|
826
829
|
}
|
|
827
830
|
let sql = 'SELECT n.nspname as "Schema",\n' +
|
|
828
831
|
' c.relname as "Name",\n' +
|
|
829
|
-
|
|
832
|
+
" CASE c.relkind" +
|
|
830
833
|
" WHEN 'r' THEN 'table'" +
|
|
831
834
|
" WHEN 'v' THEN 'view'" +
|
|
832
835
|
" WHEN 'm' THEN 'materialized view'" +
|
|
@@ -842,7 +845,7 @@ export const listTables = (opts) => {
|
|
|
842
845
|
sql += ',\n c2.relname as "Table"';
|
|
843
846
|
if (verbose) {
|
|
844
847
|
sql +=
|
|
845
|
-
|
|
848
|
+
",\n CASE c.relpersistence" +
|
|
846
849
|
" WHEN 'p' THEN 'permanent'" +
|
|
847
850
|
" WHEN 't' THEN 'temporary'" +
|
|
848
851
|
" WHEN 'u' THEN 'unlogged'" +
|
|
@@ -858,23 +861,23 @@ export const listTables = (opts) => {
|
|
|
858
861
|
// tests pin to.
|
|
859
862
|
sql +=
|
|
860
863
|
',\n pg_catalog.pg_size_pretty(pg_catalog.pg_total_relation_size(c.oid)) as "Size"' +
|
|
861
|
-
|
|
864
|
+
",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"Description\"";
|
|
862
865
|
}
|
|
863
866
|
sql +=
|
|
864
|
-
|
|
865
|
-
|
|
867
|
+
"\nFROM pg_catalog.pg_class c" +
|
|
868
|
+
"\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace";
|
|
866
869
|
if (verbose &&
|
|
867
870
|
!hideTableam &&
|
|
868
871
|
serverAtLeast(serverVersion, PG_12) &&
|
|
869
872
|
(showTables || showMatViews || showIndexes)) {
|
|
870
|
-
sql +=
|
|
873
|
+
sql += "\n LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam";
|
|
871
874
|
}
|
|
872
875
|
if (showIndexes) {
|
|
873
876
|
sql +=
|
|
874
|
-
|
|
875
|
-
|
|
877
|
+
"\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid" +
|
|
878
|
+
"\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid";
|
|
876
879
|
}
|
|
877
|
-
sql +=
|
|
880
|
+
sql += "\nWHERE c.relkind IN (";
|
|
878
881
|
const kinds = [];
|
|
879
882
|
if (showTables) {
|
|
880
883
|
kinds.push("'r'", "'p'");
|
|
@@ -894,33 +897,33 @@ export const listTables = (opts) => {
|
|
|
894
897
|
if (showForeign)
|
|
895
898
|
kinds.push("'f'");
|
|
896
899
|
kinds.push("''");
|
|
897
|
-
sql += kinds.join(
|
|
900
|
+
sql += kinds.join(",") + ")\n";
|
|
898
901
|
if (!showSystem && pattern === undefined) {
|
|
899
902
|
sql +=
|
|
900
903
|
" AND n.nspname <> 'pg_catalog'\n" +
|
|
901
904
|
" AND n.nspname !~ '^pg_toast'\n" +
|
|
902
905
|
" AND n.nspname <> 'information_schema'\n";
|
|
903
906
|
}
|
|
904
|
-
sql += patternStub(true,
|
|
905
|
-
sql += orderBy(
|
|
907
|
+
sql += patternStub(true, "n.nspname", "c.relname");
|
|
908
|
+
sql += orderBy("1,2");
|
|
906
909
|
// Upstream `describe.c::listTables` uses a type-specific title when the
|
|
907
910
|
// caller filters to a single relkind family, falling back to "relations"
|
|
908
911
|
// for mixed (or default) selections. Mirror that so `\dt` / `\dv` /
|
|
909
912
|
// `\dm` / `\di` / `\ds` / `\dE` titles match.
|
|
910
|
-
let description =
|
|
913
|
+
let description = "List of relations";
|
|
911
914
|
if (ntypes === 1) {
|
|
912
915
|
if (showTables)
|
|
913
|
-
description =
|
|
916
|
+
description = "List of tables";
|
|
914
917
|
else if (showIndexes)
|
|
915
|
-
description =
|
|
918
|
+
description = "List of indexes";
|
|
916
919
|
else if (showViews)
|
|
917
|
-
description =
|
|
920
|
+
description = "List of views";
|
|
918
921
|
else if (showMatViews)
|
|
919
|
-
description =
|
|
922
|
+
description = "List of materialized views";
|
|
920
923
|
else if (showSeq)
|
|
921
|
-
description =
|
|
924
|
+
description = "List of sequences";
|
|
922
925
|
else if (showForeign)
|
|
923
|
-
description =
|
|
926
|
+
description = "List of foreign tables";
|
|
924
927
|
}
|
|
925
928
|
return { sql, params: params(), description };
|
|
926
929
|
};
|
|
@@ -928,15 +931,15 @@ export const listPartitionedTables = (opts) => {
|
|
|
928
931
|
const { verbose, pattern, serverVersion } = opts;
|
|
929
932
|
if (serverLess(serverVersion, PG_10)) {
|
|
930
933
|
return {
|
|
931
|
-
sql:
|
|
934
|
+
sql: "/* server < 10 does not support declarative partitioning */ SELECT 1 WHERE false;",
|
|
932
935
|
params: [],
|
|
933
|
-
description:
|
|
936
|
+
description: "List of partitioned relations",
|
|
934
937
|
};
|
|
935
938
|
}
|
|
936
|
-
const rt = opts.reltypes ??
|
|
937
|
-
let showTables = rt.includes(
|
|
938
|
-
let showIndexes = rt.includes(
|
|
939
|
-
const showNested = rt.includes(
|
|
939
|
+
const rt = opts.reltypes ?? "";
|
|
940
|
+
let showTables = rt.includes("t");
|
|
941
|
+
let showIndexes = rt.includes("i");
|
|
942
|
+
const showNested = rt.includes("n");
|
|
940
943
|
if (!showTables && !showIndexes)
|
|
941
944
|
showTables = showIndexes = true;
|
|
942
945
|
const mixed = showTables && showIndexes;
|
|
@@ -945,7 +948,7 @@ export const listPartitionedTables = (opts) => {
|
|
|
945
948
|
' pg_catalog.pg_get_userbyid(c.relowner) as "Owner"';
|
|
946
949
|
if (mixed) {
|
|
947
950
|
sql +=
|
|
948
|
-
|
|
951
|
+
",\n CASE c.relkind" +
|
|
949
952
|
" WHEN 'p' THEN 'partitioned table'" +
|
|
950
953
|
" WHEN 'I' THEN 'partitioned index'" +
|
|
951
954
|
' END as "Type"';
|
|
@@ -966,51 +969,51 @@ export const listPartitionedTables = (opts) => {
|
|
|
966
969
|
sql += ',\n s.tps as "Total size"';
|
|
967
970
|
}
|
|
968
971
|
sql +=
|
|
969
|
-
|
|
972
|
+
",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"Description\"";
|
|
970
973
|
}
|
|
971
974
|
sql +=
|
|
972
|
-
|
|
973
|
-
|
|
975
|
+
"\nFROM pg_catalog.pg_class c" +
|
|
976
|
+
"\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace";
|
|
974
977
|
if (showIndexes) {
|
|
975
978
|
sql +=
|
|
976
|
-
|
|
977
|
-
|
|
979
|
+
"\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid" +
|
|
980
|
+
"\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid";
|
|
978
981
|
}
|
|
979
982
|
if (showNested || pattern !== undefined) {
|
|
980
983
|
sql +=
|
|
981
|
-
|
|
984
|
+
"\n LEFT JOIN pg_catalog.pg_inherits inh ON c.oid = inh.inhrelid";
|
|
982
985
|
}
|
|
983
986
|
if (verbose) {
|
|
984
|
-
sql +=
|
|
987
|
+
sql += "\n LEFT JOIN pg_catalog.pg_am am ON c.relam = am.oid";
|
|
985
988
|
if (serverLess(serverVersion, PG_12)) {
|
|
986
989
|
sql +=
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
990
|
+
",\n LATERAL (WITH RECURSIVE d AS (\n" +
|
|
991
|
+
" SELECT inhrelid AS oid, 1 AS level FROM pg_catalog.pg_inherits WHERE inhparent = c.oid\n" +
|
|
992
|
+
" UNION ALL\n" +
|
|
993
|
+
" SELECT inhrelid, level + 1 FROM pg_catalog.pg_inherits i JOIN d ON i.inhparent = d.oid)\n" +
|
|
994
|
+
" SELECT pg_catalog.pg_size_pretty(sum(pg_catalog.pg_table_size(d.oid))) AS tps,\n" +
|
|
995
|
+
" pg_catalog.pg_size_pretty(sum(CASE WHEN d.level = 1 THEN pg_catalog.pg_table_size(d.oid) ELSE 0 END)) AS dps\n" +
|
|
996
|
+
" FROM d) s";
|
|
994
997
|
}
|
|
995
998
|
else {
|
|
996
999
|
sql +=
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1000
|
+
",\n LATERAL (SELECT pg_catalog.pg_size_pretty(sum(\n" +
|
|
1001
|
+
" CASE WHEN ppt.isleaf AND ppt.level = 1\n" +
|
|
1002
|
+
" THEN pg_catalog.pg_table_size(ppt.relid) ELSE 0 END)) AS dps,\n" +
|
|
1003
|
+
" pg_catalog.pg_size_pretty(sum(pg_catalog.pg_table_size(ppt.relid))) AS tps\n" +
|
|
1004
|
+
" FROM pg_catalog.pg_partition_tree(c.oid) ppt) s";
|
|
1002
1005
|
}
|
|
1003
1006
|
}
|
|
1004
|
-
sql +=
|
|
1007
|
+
sql += "\nWHERE c.relkind IN (";
|
|
1005
1008
|
const kinds = [];
|
|
1006
1009
|
if (showTables)
|
|
1007
1010
|
kinds.push("'p'");
|
|
1008
1011
|
if (showIndexes)
|
|
1009
1012
|
kinds.push("'I'");
|
|
1010
1013
|
kinds.push("''");
|
|
1011
|
-
sql += kinds.join(
|
|
1014
|
+
sql += kinds.join(",") + ")\n";
|
|
1012
1015
|
if (!showNested && pattern === undefined) {
|
|
1013
|
-
sql +=
|
|
1016
|
+
sql += " AND NOT c.relispartition\n";
|
|
1014
1017
|
}
|
|
1015
1018
|
if (pattern === undefined) {
|
|
1016
1019
|
sql +=
|
|
@@ -1018,15 +1021,15 @@ export const listPartitionedTables = (opts) => {
|
|
|
1018
1021
|
" AND n.nspname !~ '^pg_toast'\n" +
|
|
1019
1022
|
" AND n.nspname <> 'information_schema'\n";
|
|
1020
1023
|
}
|
|
1021
|
-
sql += patternStub(true,
|
|
1022
|
-
sql += `ORDER BY "Schema", ${mixed ? '"Type" DESC, ' :
|
|
1024
|
+
sql += patternStub(true, "n.nspname", "c.relname");
|
|
1025
|
+
sql += `ORDER BY "Schema", ${mixed ? '"Type" DESC, ' : ""}${showNested || pattern !== undefined ? '"Parent name" NULLS FIRST, ' : ""}"Name";`;
|
|
1023
1026
|
// Mirror upstream's `tabletitle` switch: `\dPi*` lists indexes,
|
|
1024
1027
|
// `\dPt*` lists tables, and any mixed/empty form lists relations.
|
|
1025
1028
|
const description = showIndexes && !showTables
|
|
1026
|
-
?
|
|
1029
|
+
? "List of partitioned indexes"
|
|
1027
1030
|
: showTables && !showIndexes
|
|
1028
|
-
?
|
|
1029
|
-
:
|
|
1031
|
+
? "List of partitioned tables"
|
|
1032
|
+
: "List of partitioned relations";
|
|
1030
1033
|
return {
|
|
1031
1034
|
sql,
|
|
1032
1035
|
params: params(),
|
|
@@ -1047,24 +1050,24 @@ export const listLanguages = (opts) => {
|
|
|
1047
1050
|
' l.lanplcallfoid::pg_catalog.regprocedure AS "Call handler",\n' +
|
|
1048
1051
|
' l.lanvalidator::pg_catalog.regprocedure AS "Validator",\n ' +
|
|
1049
1052
|
'l.laninline::pg_catalog.regprocedure AS "Inline handler",\n ' +
|
|
1050
|
-
aclColumn(
|
|
1053
|
+
aclColumn("l.lanacl");
|
|
1051
1054
|
}
|
|
1052
1055
|
sql +=
|
|
1053
1056
|
',\n d.description AS "Description"\n' +
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
+
"FROM pg_catalog.pg_language l\n" +
|
|
1058
|
+
"LEFT JOIN pg_catalog.pg_description d\n" +
|
|
1059
|
+
" ON d.classoid = l.tableoid AND d.objoid = l.oid AND d.objsubid = 0\n";
|
|
1057
1060
|
let hasWhere = false;
|
|
1058
1061
|
if (pattern !== undefined) {
|
|
1059
|
-
sql += patternStub(hasWhere, undefined,
|
|
1062
|
+
sql += patternStub(hasWhere, undefined, "l.lanname");
|
|
1060
1063
|
hasWhere = true;
|
|
1061
1064
|
}
|
|
1062
1065
|
if (!showSystem && pattern === undefined) {
|
|
1063
|
-
sql +=
|
|
1066
|
+
sql += "WHERE l.lanplcallfoid != 0\n";
|
|
1064
1067
|
hasWhere = true;
|
|
1065
1068
|
}
|
|
1066
|
-
sql += orderBy(
|
|
1067
|
-
return { sql, params: params(), description:
|
|
1069
|
+
sql += orderBy("1");
|
|
1070
|
+
return { sql, params: params(), description: "List of languages" };
|
|
1068
1071
|
};
|
|
1069
1072
|
/* ------------------------------------------------------------------ */
|
|
1070
1073
|
/* \dD — listDomains */
|
|
@@ -1074,30 +1077,30 @@ export const listDomains = (opts) => {
|
|
|
1074
1077
|
let sql = 'SELECT n.nspname as "Schema",\n' +
|
|
1075
1078
|
' t.typname as "Name",\n' +
|
|
1076
1079
|
' pg_catalog.format_type(t.typbasetype, t.typtypmod) as "Type",\n' +
|
|
1077
|
-
|
|
1080
|
+
" (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type bt\n" +
|
|
1078
1081
|
' WHERE c.oid = t.typcollation AND bt.oid = t.typbasetype AND t.typcollation <> bt.typcollation) as "Collation",\n' +
|
|
1079
|
-
|
|
1082
|
+
" CASE WHEN t.typnotnull THEN 'not null' END as \"Nullable\",\n" +
|
|
1080
1083
|
' t.typdefault as "Default",\n' +
|
|
1081
1084
|
" pg_catalog.array_to_string(ARRAY(\n SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM pg_catalog.pg_constraint r WHERE t.oid = r.contypid AND r.contype = 'c' ORDER BY r.conname\n ), ' ') as \"Check\"";
|
|
1082
1085
|
if (verbose) {
|
|
1083
|
-
sql +=
|
|
1086
|
+
sql += ",\n " + aclColumn("t.typacl");
|
|
1084
1087
|
sql += ',\n d.description as "Description"';
|
|
1085
1088
|
}
|
|
1086
1089
|
sql +=
|
|
1087
|
-
|
|
1088
|
-
|
|
1090
|
+
"\nFROM pg_catalog.pg_type t\n" +
|
|
1091
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n";
|
|
1089
1092
|
if (verbose) {
|
|
1090
1093
|
sql +=
|
|
1091
|
-
|
|
1094
|
+
" LEFT JOIN pg_catalog.pg_description d ON d.classoid = t.tableoid AND d.objoid = t.oid AND d.objsubid = 0\n";
|
|
1092
1095
|
}
|
|
1093
1096
|
sql += "WHERE t.typtype = 'd'\n";
|
|
1094
1097
|
if (!showSystem && pattern === undefined) {
|
|
1095
1098
|
sql +=
|
|
1096
1099
|
" AND n.nspname <> 'pg_catalog'\n AND n.nspname <> 'information_schema'\n";
|
|
1097
1100
|
}
|
|
1098
|
-
sql += patternStub(true,
|
|
1099
|
-
sql += orderBy(
|
|
1100
|
-
return { sql, params: params(), description:
|
|
1101
|
+
sql += patternStub(true, "n.nspname", "t.typname");
|
|
1102
|
+
sql += orderBy("1, 2");
|
|
1103
|
+
return { sql, params: params(), description: "List of domains" };
|
|
1101
1104
|
};
|
|
1102
1105
|
/* ------------------------------------------------------------------ */
|
|
1103
1106
|
/* \dc — listConversions */
|
|
@@ -1112,20 +1115,20 @@ export const listConversions = (opts) => {
|
|
|
1112
1115
|
if (verbose)
|
|
1113
1116
|
sql += ',\n d.description AS "Description"';
|
|
1114
1117
|
sql +=
|
|
1115
|
-
|
|
1116
|
-
|
|
1118
|
+
"\nFROM pg_catalog.pg_conversion c\n" +
|
|
1119
|
+
" JOIN pg_catalog.pg_namespace n ON n.oid = c.connamespace\n";
|
|
1117
1120
|
if (verbose) {
|
|
1118
1121
|
sql +=
|
|
1119
|
-
|
|
1122
|
+
"LEFT JOIN pg_catalog.pg_description d ON d.classoid = c.tableoid AND d.objoid = c.oid AND d.objsubid = 0\n";
|
|
1120
1123
|
}
|
|
1121
|
-
sql +=
|
|
1124
|
+
sql += "WHERE true\n";
|
|
1122
1125
|
if (!showSystem && pattern === undefined) {
|
|
1123
1126
|
sql +=
|
|
1124
1127
|
" AND n.nspname <> 'pg_catalog'\n AND n.nspname <> 'information_schema'\n";
|
|
1125
1128
|
}
|
|
1126
|
-
sql += patternStub(true,
|
|
1127
|
-
sql += orderBy(
|
|
1128
|
-
return { sql, params: params(), description:
|
|
1129
|
+
sql += patternStub(true, "n.nspname", "c.conname");
|
|
1130
|
+
sql += orderBy("1, 2");
|
|
1131
|
+
return { sql, params: params(), description: "List of conversions" };
|
|
1129
1132
|
};
|
|
1130
1133
|
/* ------------------------------------------------------------------ */
|
|
1131
1134
|
/* \dconfig — describeConfigurationParameters */
|
|
@@ -1136,31 +1139,31 @@ export const describeConfigurationParameters = (opts) => {
|
|
|
1136
1139
|
if (verbose) {
|
|
1137
1140
|
sql += ', s.vartype AS "Type", s.context AS "Context", ';
|
|
1138
1141
|
if (serverAtLeast(serverVersion, PG_15)) {
|
|
1139
|
-
sql += aclColumn(
|
|
1142
|
+
sql += aclColumn("p.paracl");
|
|
1140
1143
|
}
|
|
1141
1144
|
else {
|
|
1142
1145
|
sql += 'NULL AS "Access privileges"';
|
|
1143
1146
|
}
|
|
1144
1147
|
}
|
|
1145
|
-
sql +=
|
|
1148
|
+
sql += "\nFROM pg_catalog.pg_settings s\n";
|
|
1146
1149
|
if (verbose && serverAtLeast(serverVersion, PG_15)) {
|
|
1147
1150
|
sql +=
|
|
1148
|
-
|
|
1151
|
+
" LEFT JOIN pg_catalog.pg_parameter_acl p ON pg_catalog.lower(s.name) = p.parname\n";
|
|
1149
1152
|
}
|
|
1150
1153
|
if (pattern !== undefined) {
|
|
1151
|
-
sql += patternStub(false, undefined,
|
|
1154
|
+
sql += patternStub(false, undefined, "pg_catalog.lower(s.name)");
|
|
1152
1155
|
}
|
|
1153
1156
|
else {
|
|
1154
1157
|
sql +=
|
|
1155
1158
|
"WHERE s.source <> 'default' AND s.setting IS DISTINCT FROM s.boot_val\n";
|
|
1156
1159
|
}
|
|
1157
|
-
sql += orderBy(
|
|
1160
|
+
sql += orderBy("1");
|
|
1158
1161
|
return {
|
|
1159
1162
|
sql,
|
|
1160
1163
|
params: params(),
|
|
1161
1164
|
description: pattern !== undefined
|
|
1162
|
-
?
|
|
1163
|
-
:
|
|
1165
|
+
? "List of configuration parameters"
|
|
1166
|
+
: "List of non-default configuration parameters",
|
|
1164
1167
|
};
|
|
1165
1168
|
};
|
|
1166
1169
|
/* ------------------------------------------------------------------ */
|
|
@@ -1171,15 +1174,15 @@ export const listEventTriggers = (opts) => {
|
|
|
1171
1174
|
let sql = 'SELECT evtname as "Name", evtevent as "Event", pg_catalog.pg_get_userbyid(e.evtowner) as "Owner",\n' +
|
|
1172
1175
|
" case evtenabled when 'O' then 'enabled' when 'R' then 'replica' when 'A' then 'always' when 'D' then 'disabled' end as \"Enabled\",\n" +
|
|
1173
1176
|
' e.evtfoid::pg_catalog.regproc as "Function", ' +
|
|
1174
|
-
|
|
1177
|
+
"pg_catalog.array_to_string(array(select x from pg_catalog.unnest(evttags) as t(x)), ', ') as \"Tags\"";
|
|
1175
1178
|
if (verbose) {
|
|
1176
1179
|
sql +=
|
|
1177
|
-
|
|
1180
|
+
",\npg_catalog.obj_description(e.oid, 'pg_event_trigger') as \"Description\"";
|
|
1178
1181
|
}
|
|
1179
|
-
sql +=
|
|
1180
|
-
sql += patternStub(false, undefined,
|
|
1181
|
-
sql += orderBy(
|
|
1182
|
-
return { sql, params: params(), description:
|
|
1182
|
+
sql += "\nFROM pg_catalog.pg_event_trigger e\n";
|
|
1183
|
+
sql += patternStub(false, undefined, "evtname");
|
|
1184
|
+
sql += orderBy("1");
|
|
1185
|
+
return { sql, params: params(), description: "List of event triggers" };
|
|
1183
1186
|
};
|
|
1184
1187
|
/* ------------------------------------------------------------------ */
|
|
1185
1188
|
/* \dX — listExtendedStats */
|
|
@@ -1188,44 +1191,45 @@ export const listExtendedStats = (opts) => {
|
|
|
1188
1191
|
const { verbose, serverVersion } = opts;
|
|
1189
1192
|
if (serverLess(serverVersion, PG_10)) {
|
|
1190
1193
|
return {
|
|
1191
|
-
sql:
|
|
1194
|
+
sql: "/* server < 10 does not support extended statistics */ SELECT 1 WHERE false;",
|
|
1192
1195
|
params: [],
|
|
1193
|
-
description:
|
|
1196
|
+
description: "List of extended statistics",
|
|
1194
1197
|
};
|
|
1195
1198
|
}
|
|
1196
|
-
let sql =
|
|
1199
|
+
let sql = "SELECT\n" +
|
|
1197
1200
|
'es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS "Schema",\n' +
|
|
1198
1201
|
'es.stxname AS "Name",\n';
|
|
1199
1202
|
if (serverAtLeast(serverVersion, PG_14)) {
|
|
1200
1203
|
sql +=
|
|
1201
|
-
|
|
1204
|
+
"pg_catalog.format('%s FROM %s', pg_catalog.pg_get_statisticsobjdef_columns(es.oid), es.stxrelid::pg_catalog.regclass) AS \"Definition\"";
|
|
1202
1205
|
}
|
|
1203
1206
|
else {
|
|
1204
1207
|
sql +=
|
|
1205
1208
|
"pg_catalog.format('%s FROM %s',\n" +
|
|
1206
1209
|
" (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(a.attname),', ')\n" +
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
+
" FROM pg_catalog.unnest(es.stxkeys) s(attnum)\n" +
|
|
1211
|
+
" JOIN pg_catalog.pg_attribute a\n" +
|
|
1212
|
+
" ON (es.stxrelid = a.attrelid AND a.attnum = s.attnum AND NOT a.attisdropped)),\n" +
|
|
1210
1213
|
'es.stxrelid::pg_catalog.regclass) AS "Definition"';
|
|
1211
1214
|
}
|
|
1212
1215
|
sql +=
|
|
1213
1216
|
",\nCASE WHEN 'd' = any(es.stxkind) THEN 'defined' END AS \"Ndistinct\",\n" +
|
|
1214
1217
|
"CASE WHEN 'f' = any(es.stxkind) THEN 'defined' END AS \"Dependencies\"";
|
|
1215
1218
|
if (serverAtLeast(serverVersion, PG_12)) {
|
|
1216
|
-
sql +=
|
|
1219
|
+
sql +=
|
|
1220
|
+
",\nCASE WHEN 'm' = any(es.stxkind) THEN 'defined' END AS \"MCV\"";
|
|
1217
1221
|
}
|
|
1218
1222
|
if (verbose) {
|
|
1219
1223
|
sql +=
|
|
1220
|
-
|
|
1224
|
+
", \npg_catalog.obj_description(oid, 'pg_statistic_ext') AS \"Description\"";
|
|
1221
1225
|
}
|
|
1222
|
-
sql +=
|
|
1223
|
-
sql += patternStub(false,
|
|
1224
|
-
sql += orderBy(
|
|
1226
|
+
sql += "\nFROM pg_catalog.pg_statistic_ext es\n";
|
|
1227
|
+
sql += patternStub(false, "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname");
|
|
1228
|
+
sql += orderBy("1, 2");
|
|
1225
1229
|
return {
|
|
1226
1230
|
sql,
|
|
1227
1231
|
params: params(),
|
|
1228
|
-
description:
|
|
1232
|
+
description: "List of extended statistics",
|
|
1229
1233
|
};
|
|
1230
1234
|
};
|
|
1231
1235
|
/* ------------------------------------------------------------------ */
|
|
@@ -1237,7 +1241,7 @@ export const listCasts = (opts) => {
|
|
|
1237
1241
|
' pg_catalog.format_type(casttarget, NULL) AS "Target type",\n' +
|
|
1238
1242
|
" CASE WHEN c.castmethod = 'b' THEN '(binary coercible)'\n" +
|
|
1239
1243
|
" WHEN c.castmethod = 'i' THEN '(with inout)'\n" +
|
|
1240
|
-
|
|
1244
|
+
" ELSE p.proname\n" +
|
|
1241
1245
|
' END AS "Function",\n' +
|
|
1242
1246
|
" CASE WHEN c.castcontext = 'e' THEN 'no'\n" +
|
|
1243
1247
|
" WHEN c.castcontext = 'a' THEN 'in assignment'\n" +
|
|
@@ -1254,23 +1258,23 @@ export const listCasts = (opts) => {
|
|
|
1254
1258
|
sql += ',\n d.description AS "Description"';
|
|
1255
1259
|
}
|
|
1256
1260
|
sql +=
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1261
|
+
"\nFROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n" +
|
|
1262
|
+
" ON c.castfunc = p.oid\n" +
|
|
1263
|
+
" LEFT JOIN pg_catalog.pg_type ts ON c.castsource = ts.oid\n" +
|
|
1264
|
+
" LEFT JOIN pg_catalog.pg_namespace ns ON ns.oid = ts.typnamespace\n" +
|
|
1265
|
+
" LEFT JOIN pg_catalog.pg_type tt ON c.casttarget = tt.oid\n" +
|
|
1266
|
+
" LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = tt.typnamespace\n";
|
|
1263
1267
|
if (verbose) {
|
|
1264
1268
|
sql +=
|
|
1265
|
-
|
|
1269
|
+
" LEFT JOIN pg_catalog.pg_description d ON d.classoid = c.tableoid AND d.objoid = c.oid AND d.objsubid = 0\n";
|
|
1266
1270
|
}
|
|
1267
|
-
sql +=
|
|
1268
|
-
sql += patternStub(true,
|
|
1269
|
-
sql +=
|
|
1270
|
-
sql += patternStub(true,
|
|
1271
|
-
sql +=
|
|
1272
|
-
sql += orderBy(
|
|
1273
|
-
return { sql, params: params(), description:
|
|
1271
|
+
sql += "WHERE ( (true";
|
|
1272
|
+
sql += patternStub(true, "ns.nspname", "ts.typname");
|
|
1273
|
+
sql += ") OR (true";
|
|
1274
|
+
sql += patternStub(true, "nt.nspname", "tt.typname");
|
|
1275
|
+
sql += ") )\n";
|
|
1276
|
+
sql += orderBy("1, 2");
|
|
1277
|
+
return { sql, params: params(), description: "List of casts" };
|
|
1274
1278
|
};
|
|
1275
1279
|
/* ------------------------------------------------------------------ */
|
|
1276
1280
|
/* \dO — listCollations */
|
|
@@ -1280,7 +1284,7 @@ export const listCollations = (opts) => {
|
|
|
1280
1284
|
let sql = 'SELECT\n n.nspname AS "Schema",\n c.collname AS "Name",\n';
|
|
1281
1285
|
if (serverAtLeast(serverVersion, PG_10)) {
|
|
1282
1286
|
sql +=
|
|
1283
|
-
|
|
1287
|
+
" CASE c.collprovider" +
|
|
1284
1288
|
" WHEN 'd' THEN 'default'" +
|
|
1285
1289
|
" WHEN 'b' THEN 'builtin'" +
|
|
1286
1290
|
" WHEN 'c' THEN 'libc'" +
|
|
@@ -1288,7 +1292,7 @@ export const listCollations = (opts) => {
|
|
|
1288
1292
|
' END AS "Provider",\n';
|
|
1289
1293
|
}
|
|
1290
1294
|
else {
|
|
1291
|
-
sql +=
|
|
1295
|
+
sql += " 'libc' AS \"Provider\",\n";
|
|
1292
1296
|
}
|
|
1293
1297
|
sql += ' c.collcollate AS "Collate",\n c.collctype AS "Ctype",\n';
|
|
1294
1298
|
if (serverAtLeast(serverVersion, PG_17)) {
|
|
@@ -1311,24 +1315,24 @@ export const listCollations = (opts) => {
|
|
|
1311
1315
|
" CASE WHEN c.collisdeterministic THEN 'yes' ELSE 'no' END AS \"Deterministic?\"";
|
|
1312
1316
|
}
|
|
1313
1317
|
else {
|
|
1314
|
-
sql +=
|
|
1318
|
+
sql += " 'yes' AS \"Deterministic?\"";
|
|
1315
1319
|
}
|
|
1316
1320
|
if (verbose) {
|
|
1317
1321
|
sql +=
|
|
1318
|
-
|
|
1322
|
+
",\n pg_catalog.obj_description(c.oid, 'pg_collation') AS \"Description\"";
|
|
1319
1323
|
}
|
|
1320
1324
|
sql +=
|
|
1321
|
-
|
|
1322
|
-
|
|
1325
|
+
"\nFROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n\n" +
|
|
1326
|
+
"WHERE n.oid = c.collnamespace\n";
|
|
1323
1327
|
if (!showSystem && pattern === undefined) {
|
|
1324
1328
|
sql +=
|
|
1325
1329
|
" AND n.nspname <> 'pg_catalog'\n AND n.nspname <> 'information_schema'\n";
|
|
1326
1330
|
}
|
|
1327
1331
|
sql +=
|
|
1328
|
-
|
|
1329
|
-
sql += patternStub(true,
|
|
1330
|
-
sql += orderBy(
|
|
1331
|
-
return { sql, params: params(), description:
|
|
1332
|
+
" AND c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))\n";
|
|
1333
|
+
sql += patternStub(true, "n.nspname", "c.collname");
|
|
1334
|
+
sql += orderBy("1, 2");
|
|
1335
|
+
return { sql, params: params(), description: "List of collations" };
|
|
1332
1336
|
};
|
|
1333
1337
|
/* ------------------------------------------------------------------ */
|
|
1334
1338
|
/* \dn — listSchemas */
|
|
@@ -1338,17 +1342,18 @@ export const listSchemas = (opts) => {
|
|
|
1338
1342
|
let sql = 'SELECT n.nspname AS "Name",\n' +
|
|
1339
1343
|
' pg_catalog.pg_get_userbyid(n.nspowner) AS "Owner"';
|
|
1340
1344
|
if (verbose) {
|
|
1341
|
-
sql +=
|
|
1345
|
+
sql += ",\n " + aclColumn("n.nspacl");
|
|
1342
1346
|
sql +=
|
|
1343
|
-
|
|
1347
|
+
",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"Description\"";
|
|
1344
1348
|
}
|
|
1345
|
-
sql +=
|
|
1349
|
+
sql += "\nFROM pg_catalog.pg_namespace n\n";
|
|
1346
1350
|
if (!showSystem && pattern === undefined) {
|
|
1347
|
-
sql +=
|
|
1351
|
+
sql +=
|
|
1352
|
+
"WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'\n";
|
|
1348
1353
|
}
|
|
1349
|
-
sql += patternStub(!showSystem && pattern === undefined, undefined,
|
|
1350
|
-
sql += orderBy(
|
|
1351
|
-
return { sql, params: params(), description:
|
|
1354
|
+
sql += patternStub(!showSystem && pattern === undefined, undefined, "n.nspname");
|
|
1355
|
+
sql += orderBy("1");
|
|
1356
|
+
return { sql, params: params(), description: "List of schemas" };
|
|
1352
1357
|
};
|
|
1353
1358
|
/* ------------------------------------------------------------------ */
|
|
1354
1359
|
/* \dFp — listTSParsers */
|
|
@@ -1359,27 +1364,27 @@ export const listTSParsers = (opts) => {
|
|
|
1359
1364
|
// Verbose form: fetch (oid, schema, name) so the renderer can issue
|
|
1360
1365
|
// per-parser detail queries (see describeOneTSParser below). WP-20 will
|
|
1361
1366
|
// wire the iteration.
|
|
1362
|
-
let sql =
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
sql += patternStub(false,
|
|
1366
|
-
sql += orderBy(
|
|
1367
|
+
let sql = "SELECT p.oid,\n n.nspname,\n p.prsname\n" +
|
|
1368
|
+
"FROM pg_catalog.pg_ts_parser p\n" +
|
|
1369
|
+
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n";
|
|
1370
|
+
sql += patternStub(false, "n.nspname", "p.prsname");
|
|
1371
|
+
sql += orderBy("1, 2");
|
|
1367
1372
|
return {
|
|
1368
1373
|
sql,
|
|
1369
1374
|
params: params(),
|
|
1370
|
-
description:
|
|
1375
|
+
description: "List of text search parsers (verbose)",
|
|
1371
1376
|
};
|
|
1372
1377
|
}
|
|
1373
1378
|
let sql = 'SELECT\n n.nspname as "Schema",\n p.prsname as "Name",\n' +
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
sql += patternStub(false,
|
|
1378
|
-
sql += orderBy(
|
|
1379
|
+
" pg_catalog.obj_description(p.oid, 'pg_ts_parser') as \"Description\"\n" +
|
|
1380
|
+
"FROM pg_catalog.pg_ts_parser p\n" +
|
|
1381
|
+
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n";
|
|
1382
|
+
sql += patternStub(false, "n.nspname", "p.prsname");
|
|
1383
|
+
sql += orderBy("1, 2");
|
|
1379
1384
|
return {
|
|
1380
1385
|
sql,
|
|
1381
1386
|
params: params(),
|
|
1382
|
-
description:
|
|
1387
|
+
description: "List of text search parsers",
|
|
1383
1388
|
};
|
|
1384
1389
|
};
|
|
1385
1390
|
/**
|
|
@@ -1404,7 +1409,7 @@ export const describeOneTSParser = (opts) => {
|
|
|
1404
1409
|
`UNION ALL\n` +
|
|
1405
1410
|
`SELECT 'Get token types', p.prslextype::pg_catalog.regproc, pg_catalog.obj_description(p.prslextype, 'pg_proc')\n` +
|
|
1406
1411
|
` FROM pg_catalog.pg_ts_parser p WHERE p.oid = '${oid}';`;
|
|
1407
|
-
return { sql, params: [], description:
|
|
1412
|
+
return { sql, params: [], description: "Text search parser details" };
|
|
1408
1413
|
};
|
|
1409
1414
|
/* ------------------------------------------------------------------ */
|
|
1410
1415
|
/* \dFd — listTSDictionaries */
|
|
@@ -1415,21 +1420,21 @@ export const listTSDictionaries = (opts) => {
|
|
|
1415
1420
|
if (verbose) {
|
|
1416
1421
|
sql +=
|
|
1417
1422
|
" ( SELECT COALESCE(nt.nspname, '(null)')::pg_catalog.text || '.' || t.tmplname FROM\n" +
|
|
1418
|
-
|
|
1419
|
-
|
|
1423
|
+
" pg_catalog.pg_ts_template t\n" +
|
|
1424
|
+
" LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = t.tmplnamespace\n" +
|
|
1420
1425
|
' WHERE d.dicttemplate = t.oid ) AS "Template",\n' +
|
|
1421
1426
|
' d.dictinitoption as "Init options",\n';
|
|
1422
1427
|
}
|
|
1423
1428
|
sql +=
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
sql += patternStub(false,
|
|
1428
|
-
sql += orderBy(
|
|
1429
|
+
" pg_catalog.obj_description(d.oid, 'pg_ts_dict') as \"Description\"\n" +
|
|
1430
|
+
"FROM pg_catalog.pg_ts_dict d\n" +
|
|
1431
|
+
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace\n";
|
|
1432
|
+
sql += patternStub(false, "n.nspname", "d.dictname");
|
|
1433
|
+
sql += orderBy("1, 2");
|
|
1429
1434
|
return {
|
|
1430
1435
|
sql,
|
|
1431
1436
|
params: params(),
|
|
1432
|
-
description:
|
|
1437
|
+
description: "List of text search dictionaries",
|
|
1433
1438
|
};
|
|
1434
1439
|
};
|
|
1435
1440
|
/* ------------------------------------------------------------------ */
|
|
@@ -1443,22 +1448,22 @@ export const listTSTemplates = (opts) => {
|
|
|
1443
1448
|
'SELECT\n n.nspname AS "Schema",\n t.tmplname AS "Name",\n' +
|
|
1444
1449
|
' t.tmplinit::pg_catalog.regproc AS "Init",\n' +
|
|
1445
1450
|
' t.tmpllexize::pg_catalog.regproc AS "Lexize",\n' +
|
|
1446
|
-
|
|
1451
|
+
" pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"Description\"\n";
|
|
1447
1452
|
}
|
|
1448
1453
|
else {
|
|
1449
1454
|
sql =
|
|
1450
1455
|
'SELECT\n n.nspname AS "Schema",\n t.tmplname AS "Name",\n' +
|
|
1451
|
-
|
|
1456
|
+
" pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"Description\"\n";
|
|
1452
1457
|
}
|
|
1453
1458
|
sql +=
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
sql += patternStub(false,
|
|
1457
|
-
sql += orderBy(
|
|
1459
|
+
"FROM pg_catalog.pg_ts_template t\n" +
|
|
1460
|
+
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace\n";
|
|
1461
|
+
sql += patternStub(false, "n.nspname", "t.tmplname");
|
|
1462
|
+
sql += orderBy("1, 2");
|
|
1458
1463
|
return {
|
|
1459
1464
|
sql,
|
|
1460
1465
|
params: params(),
|
|
1461
|
-
description:
|
|
1466
|
+
description: "List of text search templates",
|
|
1462
1467
|
};
|
|
1463
1468
|
};
|
|
1464
1469
|
/* ------------------------------------------------------------------ */
|
|
@@ -1467,30 +1472,30 @@ export const listTSTemplates = (opts) => {
|
|
|
1467
1472
|
export const listTSConfigs = (opts) => {
|
|
1468
1473
|
const { verbose } = opts;
|
|
1469
1474
|
if (verbose) {
|
|
1470
|
-
let sql =
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
sql += patternStub(true,
|
|
1477
|
-
sql += orderBy(
|
|
1475
|
+
let sql = "SELECT c.oid, c.cfgname, n.nspname, p.prsname, np.nspname as pnspname\n" +
|
|
1476
|
+
"FROM pg_catalog.pg_ts_config c\n" +
|
|
1477
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace,\n" +
|
|
1478
|
+
" pg_catalog.pg_ts_parser p\n" +
|
|
1479
|
+
" LEFT JOIN pg_catalog.pg_namespace np ON np.oid = p.prsnamespace\n" +
|
|
1480
|
+
"WHERE p.oid = c.cfgparser\n";
|
|
1481
|
+
sql += patternStub(true, "n.nspname", "c.cfgname");
|
|
1482
|
+
sql += orderBy("3, 2");
|
|
1478
1483
|
return {
|
|
1479
1484
|
sql,
|
|
1480
1485
|
params: params(),
|
|
1481
|
-
description:
|
|
1486
|
+
description: "List of text search configurations (verbose)",
|
|
1482
1487
|
};
|
|
1483
1488
|
}
|
|
1484
1489
|
let sql = 'SELECT\n n.nspname as "Schema",\n c.cfgname as "Name",\n' +
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
sql += patternStub(false,
|
|
1489
|
-
sql += orderBy(
|
|
1490
|
+
" pg_catalog.obj_description(c.oid, 'pg_ts_config') as \"Description\"\n" +
|
|
1491
|
+
"FROM pg_catalog.pg_ts_config c\n" +
|
|
1492
|
+
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace\n";
|
|
1493
|
+
sql += patternStub(false, "n.nspname", "c.cfgname");
|
|
1494
|
+
sql += orderBy("1, 2");
|
|
1490
1495
|
return {
|
|
1491
1496
|
sql,
|
|
1492
1497
|
params: params(),
|
|
1493
|
-
description:
|
|
1498
|
+
description: "List of text search configurations",
|
|
1494
1499
|
};
|
|
1495
1500
|
};
|
|
1496
1501
|
/* ------------------------------------------------------------------ */
|
|
@@ -1503,24 +1508,24 @@ export const listForeignDataWrappers = (opts) => {
|
|
|
1503
1508
|
' fdw.fdwhandler::pg_catalog.regproc AS "Handler",\n' +
|
|
1504
1509
|
' fdw.fdwvalidator::pg_catalog.regproc AS "Validator"';
|
|
1505
1510
|
if (verbose) {
|
|
1506
|
-
sql +=
|
|
1511
|
+
sql += ",\n " + aclColumn("fdwacl");
|
|
1507
1512
|
sql +=
|
|
1508
1513
|
",\n CASE WHEN fdwoptions IS NULL THEN '' ELSE\n" +
|
|
1509
1514
|
" '(' || pg_catalog.array_to_string(ARRAY(SELECT pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value) FROM pg_catalog.pg_options_to_table(fdwoptions)), ', ') || ')'\n" +
|
|
1510
1515
|
' END AS "FDW options",\n' +
|
|
1511
1516
|
' d.description AS "Description" ';
|
|
1512
1517
|
}
|
|
1513
|
-
sql +=
|
|
1518
|
+
sql += "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n";
|
|
1514
1519
|
if (verbose) {
|
|
1515
1520
|
sql +=
|
|
1516
|
-
|
|
1521
|
+
"LEFT JOIN pg_catalog.pg_description d ON d.classoid = fdw.tableoid AND d.objoid = fdw.oid AND d.objsubid = 0\n";
|
|
1517
1522
|
}
|
|
1518
|
-
sql += patternStub(false, undefined,
|
|
1519
|
-
sql += orderBy(
|
|
1523
|
+
sql += patternStub(false, undefined, "fdwname");
|
|
1524
|
+
sql += orderBy("1");
|
|
1520
1525
|
return {
|
|
1521
1526
|
sql,
|
|
1522
1527
|
params: params(),
|
|
1523
|
-
description:
|
|
1528
|
+
description: "List of foreign-data wrappers",
|
|
1524
1529
|
};
|
|
1525
1530
|
};
|
|
1526
1531
|
/* ------------------------------------------------------------------ */
|
|
@@ -1532,7 +1537,7 @@ export const listForeignServers = (opts) => {
|
|
|
1532
1537
|
' pg_catalog.pg_get_userbyid(s.srvowner) AS "Owner",\n' +
|
|
1533
1538
|
' f.fdwname AS "Foreign-data wrapper"';
|
|
1534
1539
|
if (verbose) {
|
|
1535
|
-
sql +=
|
|
1540
|
+
sql += ",\n " + aclColumn("s.srvacl");
|
|
1536
1541
|
sql +=
|
|
1537
1542
|
',\n s.srvtype AS "Type",\n' +
|
|
1538
1543
|
' s.srvversion AS "Version",\n' +
|
|
@@ -1542,15 +1547,15 @@ export const listForeignServers = (opts) => {
|
|
|
1542
1547
|
' d.description AS "Description"';
|
|
1543
1548
|
}
|
|
1544
1549
|
sql +=
|
|
1545
|
-
|
|
1546
|
-
|
|
1550
|
+
"\nFROM pg_catalog.pg_foreign_server s\n" +
|
|
1551
|
+
" JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n";
|
|
1547
1552
|
if (verbose) {
|
|
1548
1553
|
sql +=
|
|
1549
|
-
|
|
1554
|
+
"LEFT JOIN pg_catalog.pg_description d ON d.classoid = s.tableoid AND d.objoid = s.oid AND d.objsubid = 0\n";
|
|
1550
1555
|
}
|
|
1551
|
-
sql += patternStub(false, undefined,
|
|
1552
|
-
sql += orderBy(
|
|
1553
|
-
return { sql, params: params(), description:
|
|
1556
|
+
sql += patternStub(false, undefined, "s.srvname");
|
|
1557
|
+
sql += orderBy("1");
|
|
1558
|
+
return { sql, params: params(), description: "List of foreign servers" };
|
|
1554
1559
|
};
|
|
1555
1560
|
/* ------------------------------------------------------------------ */
|
|
1556
1561
|
/* \deu — listUserMappings */
|
|
@@ -1564,10 +1569,10 @@ export const listUserMappings = (opts) => {
|
|
|
1564
1569
|
" '(' || pg_catalog.array_to_string(ARRAY(SELECT pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value) FROM pg_catalog.pg_options_to_table(umoptions)), ', ') || ')'\n" +
|
|
1565
1570
|
' END AS "FDW options"';
|
|
1566
1571
|
}
|
|
1567
|
-
sql +=
|
|
1568
|
-
sql += patternStub(false, undefined,
|
|
1569
|
-
sql += orderBy(
|
|
1570
|
-
return { sql, params: params(), description:
|
|
1572
|
+
sql += "\nFROM pg_catalog.pg_user_mappings um\n";
|
|
1573
|
+
sql += patternStub(false, undefined, "um.srvname");
|
|
1574
|
+
sql += orderBy("1, 2");
|
|
1575
|
+
return { sql, params: params(), description: "List of user mappings" };
|
|
1571
1576
|
};
|
|
1572
1577
|
/* ------------------------------------------------------------------ */
|
|
1573
1578
|
/* \det — listForeignTables */
|
|
@@ -1583,17 +1588,17 @@ export const listForeignTables = (opts) => {
|
|
|
1583
1588
|
' d.description AS "Description"';
|
|
1584
1589
|
}
|
|
1585
1590
|
sql +=
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1591
|
+
"\nFROM pg_catalog.pg_foreign_table ft\n" +
|
|
1592
|
+
" INNER JOIN pg_catalog.pg_class c ON c.oid = ft.ftrelid\n" +
|
|
1593
|
+
" INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" +
|
|
1594
|
+
" INNER JOIN pg_catalog.pg_foreign_server s ON s.oid = ft.ftserver\n";
|
|
1590
1595
|
if (verbose) {
|
|
1591
1596
|
sql +=
|
|
1592
|
-
|
|
1597
|
+
" LEFT JOIN pg_catalog.pg_description d ON d.classoid = c.tableoid AND d.objoid = c.oid AND d.objsubid = 0\n";
|
|
1593
1598
|
}
|
|
1594
|
-
sql += patternStub(false,
|
|
1595
|
-
sql += orderBy(
|
|
1596
|
-
return { sql, params: params(), description:
|
|
1599
|
+
sql += patternStub(false, "n.nspname", "c.relname");
|
|
1600
|
+
sql += orderBy("1, 2");
|
|
1601
|
+
return { sql, params: params(), description: "List of foreign tables" };
|
|
1597
1602
|
};
|
|
1598
1603
|
/* ------------------------------------------------------------------ */
|
|
1599
1604
|
/* \dx — listExtensions / \dx+ — listExtensionContents */
|
|
@@ -1609,30 +1614,30 @@ export const listExtensions = (opts) => {
|
|
|
1609
1614
|
}
|
|
1610
1615
|
sql +=
|
|
1611
1616
|
'n.nspname AS "Schema", d.description AS "Description"\n' +
|
|
1612
|
-
|
|
1613
|
-
|
|
1617
|
+
"FROM pg_catalog.pg_extension e " +
|
|
1618
|
+
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace " +
|
|
1614
1619
|
"LEFT JOIN pg_catalog.pg_description d ON d.objoid = e.oid AND d.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass";
|
|
1615
1620
|
if (hasDefaultVersion) {
|
|
1616
1621
|
sql +=
|
|
1617
|
-
|
|
1622
|
+
" LEFT JOIN pg_catalog.pg_available_extensions() ae(name, default_version, comment) ON ae.name = e.extname";
|
|
1618
1623
|
}
|
|
1619
|
-
sql +=
|
|
1620
|
-
sql += patternStub(false, undefined,
|
|
1621
|
-
sql += orderBy(
|
|
1624
|
+
sql += "\n";
|
|
1625
|
+
sql += patternStub(false, undefined, "e.extname");
|
|
1626
|
+
sql += orderBy("1");
|
|
1622
1627
|
return {
|
|
1623
1628
|
sql,
|
|
1624
1629
|
params: params(),
|
|
1625
|
-
description:
|
|
1630
|
+
description: "List of installed extensions",
|
|
1626
1631
|
};
|
|
1627
1632
|
};
|
|
1628
1633
|
export const listExtensionContents = () => {
|
|
1629
|
-
let sql =
|
|
1630
|
-
sql += patternStub(false, undefined,
|
|
1631
|
-
sql += orderBy(
|
|
1634
|
+
let sql = "SELECT e.extname, e.oid\nFROM pg_catalog.pg_extension e\n";
|
|
1635
|
+
sql += patternStub(false, undefined, "e.extname");
|
|
1636
|
+
sql += orderBy("1");
|
|
1632
1637
|
return {
|
|
1633
1638
|
sql,
|
|
1634
1639
|
params: params(),
|
|
1635
|
-
description:
|
|
1640
|
+
description: "Get matching extensions to list contents for",
|
|
1636
1641
|
};
|
|
1637
1642
|
};
|
|
1638
1643
|
/**
|
|
@@ -1640,10 +1645,10 @@ export const listExtensionContents = () => {
|
|
|
1640
1645
|
*/
|
|
1641
1646
|
export const listOneExtensionContents = (opts) => {
|
|
1642
1647
|
const sql = 'SELECT pg_catalog.pg_describe_object(classid, objid, 0) AS "Object description"\n' +
|
|
1643
|
-
|
|
1648
|
+
"FROM pg_catalog.pg_depend\n" +
|
|
1644
1649
|
`WHERE refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass AND refobjid = '${opts.oid}' AND deptype = 'e'\n` +
|
|
1645
|
-
|
|
1646
|
-
return { sql, params: [], description:
|
|
1650
|
+
"ORDER BY 1;";
|
|
1651
|
+
return { sql, params: [], description: "Objects in extension" };
|
|
1647
1652
|
};
|
|
1648
1653
|
/* ------------------------------------------------------------------ */
|
|
1649
1654
|
/* \dRp — listPublications / describePublications (\dRp+) */
|
|
@@ -1652,9 +1657,9 @@ export const listPublications = (opts) => {
|
|
|
1652
1657
|
const { serverVersion } = opts;
|
|
1653
1658
|
if (serverLess(serverVersion, PG_10)) {
|
|
1654
1659
|
return {
|
|
1655
|
-
sql:
|
|
1660
|
+
sql: "/* server < 10 does not support publications */ SELECT 1 WHERE false;",
|
|
1656
1661
|
params: [],
|
|
1657
|
-
description:
|
|
1662
|
+
description: "List of publications",
|
|
1658
1663
|
};
|
|
1659
1664
|
}
|
|
1660
1665
|
let sql = 'SELECT pubname AS "Name",\n' +
|
|
@@ -1672,16 +1677,16 @@ export const listPublications = (opts) => {
|
|
|
1672
1677
|
// columns" in `\dRp`. Values: 'n' = none, 's' = stored.
|
|
1673
1678
|
if (serverAtLeast(serverVersion, PG_18)) {
|
|
1674
1679
|
sql +=
|
|
1675
|
-
|
|
1680
|
+
",\n (CASE pubgencols " +
|
|
1676
1681
|
"WHEN 'n' THEN 'none' WHEN 's' THEN 'stored' END) AS \"Generated columns\"";
|
|
1677
1682
|
}
|
|
1678
1683
|
if (serverAtLeast(serverVersion, PG_13)) {
|
|
1679
1684
|
sql += ',\n pubviaroot AS "Via root"';
|
|
1680
1685
|
}
|
|
1681
|
-
sql +=
|
|
1682
|
-
sql += patternStub(false, undefined,
|
|
1683
|
-
sql += orderBy(
|
|
1684
|
-
return { sql, params: params(), description:
|
|
1686
|
+
sql += "\nFROM pg_catalog.pg_publication\n";
|
|
1687
|
+
sql += patternStub(false, undefined, "pubname");
|
|
1688
|
+
sql += orderBy("1");
|
|
1689
|
+
return { sql, params: params(), description: "List of publications" };
|
|
1685
1690
|
};
|
|
1686
1691
|
/**
|
|
1687
1692
|
* Detail-lookup query for `\dRp+`. Output columns match the unmodified
|
|
@@ -1692,19 +1697,19 @@ export const describePublications = (opts) => {
|
|
|
1692
1697
|
const { serverVersion } = opts;
|
|
1693
1698
|
if (serverLess(serverVersion, PG_10)) {
|
|
1694
1699
|
return {
|
|
1695
|
-
sql:
|
|
1700
|
+
sql: "/* server < 10 does not support publications */ SELECT 1 WHERE false;",
|
|
1696
1701
|
params: [],
|
|
1697
|
-
description:
|
|
1702
|
+
description: "Details of publications",
|
|
1698
1703
|
};
|
|
1699
1704
|
}
|
|
1700
1705
|
const hasSeq = serverAtLeast(serverVersion, 19);
|
|
1701
1706
|
const hasTrunc = serverAtLeast(serverVersion, PG_11);
|
|
1702
1707
|
const hasGen = serverAtLeast(serverVersion, PG_18);
|
|
1703
1708
|
const hasViaRoot = serverAtLeast(serverVersion, PG_13);
|
|
1704
|
-
let sql =
|
|
1705
|
-
sql += hasSeq ?
|
|
1706
|
-
sql +=
|
|
1707
|
-
sql += hasTrunc ?
|
|
1709
|
+
let sql = "SELECT oid, pubname,\n pg_catalog.pg_get_userbyid(pubowner) AS owner,\n puballtables";
|
|
1710
|
+
sql += hasSeq ? ", puballsequences" : ", false AS puballsequences";
|
|
1711
|
+
sql += ", pubinsert, pubupdate, pubdelete";
|
|
1712
|
+
sql += hasTrunc ? ", pubtruncate" : ", false AS pubtruncate";
|
|
1708
1713
|
if (hasGen) {
|
|
1709
1714
|
sql +=
|
|
1710
1715
|
", (CASE pubgencols WHEN 'n' THEN 'none' WHEN 's' THEN 'stored' END) AS pubgencols";
|
|
@@ -1712,12 +1717,12 @@ export const describePublications = (opts) => {
|
|
|
1712
1717
|
else {
|
|
1713
1718
|
sql += ", 'none' AS pubgencols";
|
|
1714
1719
|
}
|
|
1715
|
-
sql += hasViaRoot ?
|
|
1720
|
+
sql += hasViaRoot ? ", pubviaroot" : ", false AS pubviaroot";
|
|
1716
1721
|
sql += ", pg_catalog.obj_description(oid, 'pg_publication')";
|
|
1717
|
-
sql +=
|
|
1718
|
-
sql += patternStub(false, undefined,
|
|
1719
|
-
sql += orderBy(
|
|
1720
|
-
return { sql, params: params(), description:
|
|
1722
|
+
sql += "\nFROM pg_catalog.pg_publication\n";
|
|
1723
|
+
sql += patternStub(false, undefined, "pubname");
|
|
1724
|
+
sql += orderBy("2");
|
|
1725
|
+
return { sql, params: params(), description: "Details of publications" };
|
|
1721
1726
|
};
|
|
1722
1727
|
/* ------------------------------------------------------------------ */
|
|
1723
1728
|
/* \dRs — describeSubscriptions */
|
|
@@ -1726,9 +1731,9 @@ export const describeSubscriptions = (opts) => {
|
|
|
1726
1731
|
const { verbose, serverVersion } = opts;
|
|
1727
1732
|
if (serverLess(serverVersion, PG_10)) {
|
|
1728
1733
|
return {
|
|
1729
|
-
sql:
|
|
1734
|
+
sql: "/* server < 10 does not support subscriptions */ SELECT 1 WHERE false;",
|
|
1730
1735
|
params: [],
|
|
1731
|
-
description:
|
|
1736
|
+
description: "List of subscriptions",
|
|
1732
1737
|
};
|
|
1733
1738
|
}
|
|
1734
1739
|
let sql = 'SELECT subname AS "Name"\n' +
|
|
@@ -1740,7 +1745,7 @@ export const describeSubscriptions = (opts) => {
|
|
|
1740
1745
|
sql += ', subbinary AS "Binary"\n';
|
|
1741
1746
|
if (serverAtLeast(serverVersion, PG_16)) {
|
|
1742
1747
|
sql +=
|
|
1743
|
-
|
|
1748
|
+
", (CASE substream\n" +
|
|
1744
1749
|
" WHEN 'f' THEN 'off'\n" +
|
|
1745
1750
|
" WHEN 't' THEN 'on'\n" +
|
|
1746
1751
|
" WHEN 'p' THEN 'parallel'\n" +
|
|
@@ -1771,65 +1776,65 @@ export const describeSubscriptions = (opts) => {
|
|
|
1771
1776
|
sql += ', subskiplsn AS "Skip LSN"\n';
|
|
1772
1777
|
}
|
|
1773
1778
|
sql +=
|
|
1774
|
-
|
|
1779
|
+
", pg_catalog.obj_description(oid, 'pg_subscription') AS \"Description\"\n";
|
|
1775
1780
|
}
|
|
1776
1781
|
sql +=
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
sql += patternStub(true, undefined,
|
|
1780
|
-
sql += orderBy(
|
|
1781
|
-
return { sql, params: params(), description:
|
|
1782
|
+
"FROM pg_catalog.pg_subscription\n" +
|
|
1783
|
+
"WHERE subdbid = (SELECT oid FROM pg_catalog.pg_database WHERE datname = pg_catalog.current_database())";
|
|
1784
|
+
sql += patternStub(true, undefined, "subname");
|
|
1785
|
+
sql += orderBy("1");
|
|
1786
|
+
return { sql, params: params(), description: "List of subscriptions" };
|
|
1782
1787
|
};
|
|
1783
1788
|
export const listOperatorClasses = (opts) => {
|
|
1784
1789
|
const { verbose } = opts;
|
|
1785
1790
|
let sql = 'SELECT\n am.amname AS "AM",\n' +
|
|
1786
1791
|
' pg_catalog.format_type(c.opcintype, NULL) AS "Input type",\n' +
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1792
|
+
" CASE\n" +
|
|
1793
|
+
" WHEN c.opckeytype <> 0 AND c.opckeytype <> c.opcintype\n" +
|
|
1794
|
+
" THEN pg_catalog.format_type(c.opckeytype, NULL)\n" +
|
|
1795
|
+
" ELSE NULL\n" +
|
|
1791
1796
|
' END AS "Storage type",\n' +
|
|
1792
|
-
|
|
1793
|
-
|
|
1797
|
+
" CASE\n" +
|
|
1798
|
+
" WHEN pg_catalog.pg_opclass_is_visible(c.oid)\n" +
|
|
1794
1799
|
" THEN pg_catalog.format('%I', c.opcname)\n" +
|
|
1795
1800
|
" ELSE pg_catalog.format('%I.%I', n.nspname, c.opcname)\n" +
|
|
1796
1801
|
' END AS "Operator class",\n' +
|
|
1797
1802
|
" (CASE WHEN c.opcdefault THEN 'yes' ELSE 'no' END) AS \"Default?\"";
|
|
1798
1803
|
if (verbose) {
|
|
1799
1804
|
sql +=
|
|
1800
|
-
|
|
1801
|
-
|
|
1805
|
+
",\n CASE\n" +
|
|
1806
|
+
" WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n" +
|
|
1802
1807
|
" THEN pg_catalog.format('%I', of.opfname)\n" +
|
|
1803
1808
|
" ELSE pg_catalog.format('%I.%I', ofn.nspname, of.opfname)\n" +
|
|
1804
1809
|
' END AS "Operator family",\n' +
|
|
1805
1810
|
' pg_catalog.pg_get_userbyid(c.opcowner) AS "Owner"\n';
|
|
1806
1811
|
}
|
|
1807
1812
|
sql +=
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
+
"\nFROM pg_catalog.pg_opclass c\n" +
|
|
1814
|
+
" LEFT JOIN pg_catalog.pg_am am on am.oid = c.opcmethod\n" +
|
|
1815
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.opcnamespace\n" +
|
|
1816
|
+
" LEFT JOIN pg_catalog.pg_type t ON t.oid = c.opcintype\n" +
|
|
1817
|
+
" LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n";
|
|
1813
1818
|
if (verbose) {
|
|
1814
1819
|
sql +=
|
|
1815
|
-
|
|
1816
|
-
|
|
1820
|
+
" LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = c.opcfamily\n" +
|
|
1821
|
+
" LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace\n";
|
|
1817
1822
|
}
|
|
1818
1823
|
let hasWhere = false;
|
|
1819
1824
|
if (opts.amPattern !== undefined) {
|
|
1820
|
-
sql += patternStub(hasWhere, undefined,
|
|
1825
|
+
sql += patternStub(hasWhere, undefined, "am.amname");
|
|
1821
1826
|
hasWhere = true;
|
|
1822
1827
|
}
|
|
1823
1828
|
if (opts.typePattern !== undefined) {
|
|
1824
|
-
sql += patternStub(hasWhere,
|
|
1829
|
+
sql += patternStub(hasWhere, "tn.nspname", "t.typname");
|
|
1825
1830
|
}
|
|
1826
|
-
sql += orderBy(
|
|
1831
|
+
sql += orderBy("1, 2, 4");
|
|
1827
1832
|
const ps = [];
|
|
1828
1833
|
if (opts.amPattern !== undefined)
|
|
1829
1834
|
ps.push(opts.amPattern);
|
|
1830
1835
|
if (opts.typePattern !== undefined)
|
|
1831
1836
|
ps.push(opts.typePattern);
|
|
1832
|
-
return { sql, params: ps, description:
|
|
1837
|
+
return { sql, params: ps, description: "List of operator classes" };
|
|
1833
1838
|
};
|
|
1834
1839
|
/* ------------------------------------------------------------------ */
|
|
1835
1840
|
/* \dAf — listOperatorFamilies */
|
|
@@ -1837,56 +1842,56 @@ export const listOperatorClasses = (opts) => {
|
|
|
1837
1842
|
export const listOperatorFamilies = (opts) => {
|
|
1838
1843
|
const { verbose } = opts;
|
|
1839
1844
|
let sql = 'SELECT\n am.amname AS "AM",\n' +
|
|
1840
|
-
|
|
1841
|
-
|
|
1845
|
+
" CASE\n" +
|
|
1846
|
+
" WHEN pg_catalog.pg_opfamily_is_visible(f.oid)\n" +
|
|
1842
1847
|
" THEN pg_catalog.format('%I', f.opfname)\n" +
|
|
1843
1848
|
" ELSE pg_catalog.format('%I.%I', n.nspname, f.opfname)\n" +
|
|
1844
1849
|
' END AS "Operator family",\n' +
|
|
1845
|
-
|
|
1850
|
+
" (SELECT\n" +
|
|
1846
1851
|
" pg_catalog.string_agg(pg_catalog.format_type(oc.opcintype, NULL), ', ')\n" +
|
|
1847
|
-
|
|
1852
|
+
" FROM pg_catalog.pg_opclass oc\n" +
|
|
1848
1853
|
' WHERE oc.opcfamily = f.oid) "Applicable types"';
|
|
1849
1854
|
if (verbose) {
|
|
1850
1855
|
sql += ',\n pg_catalog.pg_get_userbyid(f.opfowner) AS "Owner"\n';
|
|
1851
1856
|
}
|
|
1852
1857
|
sql +=
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1858
|
+
"\nFROM pg_catalog.pg_opfamily f\n" +
|
|
1859
|
+
" LEFT JOIN pg_catalog.pg_am am on am.oid = f.opfmethod\n" +
|
|
1860
|
+
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = f.opfnamespace\n";
|
|
1856
1861
|
let hasWhere = false;
|
|
1857
1862
|
if (opts.amPattern !== undefined) {
|
|
1858
|
-
sql += patternStub(hasWhere, undefined,
|
|
1863
|
+
sql += patternStub(hasWhere, undefined, "am.amname");
|
|
1859
1864
|
hasWhere = true;
|
|
1860
1865
|
}
|
|
1861
1866
|
if (opts.typePattern !== undefined) {
|
|
1862
1867
|
sql +=
|
|
1863
|
-
` ${hasWhere ?
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
patternStub(true,
|
|
1869
|
-
|
|
1868
|
+
` ${hasWhere ? "AND" : "WHERE"} EXISTS (\n` +
|
|
1869
|
+
" SELECT 1 FROM pg_catalog.pg_type t\n" +
|
|
1870
|
+
" JOIN pg_catalog.pg_opclass oc ON oc.opcintype = t.oid\n" +
|
|
1871
|
+
" LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n" +
|
|
1872
|
+
" WHERE oc.opcfamily = f.oid\n" +
|
|
1873
|
+
patternStub(true, "tn.nspname", "t.typname") +
|
|
1874
|
+
" )\n";
|
|
1870
1875
|
}
|
|
1871
|
-
sql += orderBy(
|
|
1876
|
+
sql += orderBy("1, 2");
|
|
1872
1877
|
const ps = [];
|
|
1873
1878
|
if (opts.amPattern !== undefined)
|
|
1874
1879
|
ps.push(opts.amPattern);
|
|
1875
1880
|
if (opts.typePattern !== undefined)
|
|
1876
1881
|
ps.push(opts.typePattern);
|
|
1877
|
-
return { sql, params: ps, description:
|
|
1882
|
+
return { sql, params: ps, description: "List of operator families" };
|
|
1878
1883
|
};
|
|
1879
1884
|
export const listOpFamilyOperators = (opts) => {
|
|
1880
1885
|
const { verbose, serverVersion } = opts;
|
|
1881
1886
|
let sql = 'SELECT\n am.amname AS "AM",\n' +
|
|
1882
|
-
|
|
1883
|
-
|
|
1887
|
+
" CASE\n" +
|
|
1888
|
+
" WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n" +
|
|
1884
1889
|
" THEN pg_catalog.format('%I', of.opfname)\n" +
|
|
1885
1890
|
" ELSE pg_catalog.format('%I.%I', nsf.nspname, of.opfname)\n" +
|
|
1886
1891
|
' END AS "Operator family",\n' +
|
|
1887
1892
|
' o.amopopr::pg_catalog.regoperator AS "Operator"\n,' +
|
|
1888
1893
|
' o.amopstrategy AS "Strategy",\n' +
|
|
1889
|
-
|
|
1894
|
+
" CASE o.amoppurpose\n" +
|
|
1890
1895
|
" WHEN 'o' THEN 'ordering'\n" +
|
|
1891
1896
|
" WHEN 's' THEN 'search'\n" +
|
|
1892
1897
|
' END AS "Purpose"\n';
|
|
@@ -1898,36 +1903,36 @@ export const listOpFamilyOperators = (opts) => {
|
|
|
1898
1903
|
sql +=
|
|
1899
1904
|
",\n CASE WHEN p.proleakproof THEN 'yes' ELSE 'no' END AS \"Leakproof?\"";
|
|
1900
1905
|
}
|
|
1901
|
-
sql +=
|
|
1906
|
+
sql += "\n";
|
|
1902
1907
|
}
|
|
1903
1908
|
sql +=
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1909
|
+
"FROM pg_catalog.pg_amop o\n" +
|
|
1910
|
+
" LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n" +
|
|
1911
|
+
" LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod AND am.oid = o.amopmethod\n" +
|
|
1912
|
+
" LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n";
|
|
1908
1913
|
if (verbose) {
|
|
1909
1914
|
sql +=
|
|
1910
|
-
|
|
1915
|
+
" LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n";
|
|
1911
1916
|
if (serverAtLeast(serverVersion, PG_18)) {
|
|
1912
1917
|
sql +=
|
|
1913
|
-
|
|
1914
|
-
|
|
1918
|
+
" LEFT JOIN pg_catalog.pg_operator op ON op.oid = o.amopopr\n" +
|
|
1919
|
+
" LEFT JOIN pg_catalog.pg_proc p ON p.oid = op.oprcode\n";
|
|
1915
1920
|
}
|
|
1916
1921
|
}
|
|
1917
1922
|
let hasWhere = false;
|
|
1918
1923
|
if (opts.amPattern !== undefined) {
|
|
1919
|
-
sql += patternStub(hasWhere, undefined,
|
|
1924
|
+
sql += patternStub(hasWhere, undefined, "am.amname");
|
|
1920
1925
|
hasWhere = true;
|
|
1921
1926
|
}
|
|
1922
1927
|
if (opts.familyPattern !== undefined) {
|
|
1923
|
-
sql += patternStub(hasWhere,
|
|
1928
|
+
sql += patternStub(hasWhere, "nsf.nspname", "of.opfname");
|
|
1924
1929
|
}
|
|
1925
1930
|
sql +=
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
+
"ORDER BY 1, 2,\n" +
|
|
1932
|
+
" o.amoplefttype = o.amoprighttype DESC,\n" +
|
|
1933
|
+
" pg_catalog.format_type(o.amoplefttype, NULL),\n" +
|
|
1934
|
+
" pg_catalog.format_type(o.amoprighttype, NULL),\n" +
|
|
1935
|
+
" o.amopstrategy;";
|
|
1931
1936
|
const ps = [];
|
|
1932
1937
|
if (opts.amPattern !== undefined)
|
|
1933
1938
|
ps.push(opts.amPattern);
|
|
@@ -1936,7 +1941,7 @@ export const listOpFamilyOperators = (opts) => {
|
|
|
1936
1941
|
return {
|
|
1937
1942
|
sql,
|
|
1938
1943
|
params: ps,
|
|
1939
|
-
description:
|
|
1944
|
+
description: "List of operators of operator families",
|
|
1940
1945
|
};
|
|
1941
1946
|
};
|
|
1942
1947
|
/* ------------------------------------------------------------------ */
|
|
@@ -1945,8 +1950,8 @@ export const listOpFamilyOperators = (opts) => {
|
|
|
1945
1950
|
export const listOpFamilyFunctions = (opts) => {
|
|
1946
1951
|
const { verbose } = opts;
|
|
1947
1952
|
let sql = 'SELECT\n am.amname AS "AM",\n' +
|
|
1948
|
-
|
|
1949
|
-
|
|
1953
|
+
" CASE\n" +
|
|
1954
|
+
" WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n" +
|
|
1950
1955
|
" THEN pg_catalog.format('%I', of.opfname)\n" +
|
|
1951
1956
|
" ELSE pg_catalog.format('%I.%I', ns.nspname, of.opfname)\n" +
|
|
1952
1957
|
' END AS "Operator family",\n' +
|
|
@@ -1957,21 +1962,21 @@ export const listOpFamilyFunctions = (opts) => {
|
|
|
1957
1962
|
? ', ap.amproc::pg_catalog.regprocedure AS "Function"\n'
|
|
1958
1963
|
: ', p.proname AS "Function"\n';
|
|
1959
1964
|
sql +=
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
+
"FROM pg_catalog.pg_amproc ap\n" +
|
|
1966
|
+
" LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = ap.amprocfamily\n" +
|
|
1967
|
+
" LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod\n" +
|
|
1968
|
+
" LEFT JOIN pg_catalog.pg_namespace ns ON of.opfnamespace = ns.oid\n" +
|
|
1969
|
+
" LEFT JOIN pg_catalog.pg_proc p ON ap.amproc = p.oid\n";
|
|
1965
1970
|
let hasWhere = false;
|
|
1966
1971
|
if (opts.amPattern !== undefined) {
|
|
1967
|
-
sql += patternStub(hasWhere, undefined,
|
|
1972
|
+
sql += patternStub(hasWhere, undefined, "am.amname");
|
|
1968
1973
|
hasWhere = true;
|
|
1969
1974
|
}
|
|
1970
1975
|
if (opts.familyPattern !== undefined) {
|
|
1971
|
-
sql += patternStub(hasWhere,
|
|
1976
|
+
sql += patternStub(hasWhere, "ns.nspname", "of.opfname");
|
|
1972
1977
|
}
|
|
1973
1978
|
sql +=
|
|
1974
|
-
|
|
1979
|
+
"ORDER BY 1, 2,\n ap.amproclefttype = ap.amprocrighttype DESC,\n 3, 4, 5;";
|
|
1975
1980
|
const ps = [];
|
|
1976
1981
|
if (opts.amPattern !== undefined)
|
|
1977
1982
|
ps.push(opts.amPattern);
|
|
@@ -1980,7 +1985,7 @@ export const listOpFamilyFunctions = (opts) => {
|
|
|
1980
1985
|
return {
|
|
1981
1986
|
sql,
|
|
1982
1987
|
params: ps,
|
|
1983
|
-
description:
|
|
1988
|
+
description: "List of support functions of operator families",
|
|
1984
1989
|
};
|
|
1985
1990
|
};
|
|
1986
1991
|
/* ------------------------------------------------------------------ */
|
|
@@ -1990,13 +1995,13 @@ export const listLargeObjects = (opts) => {
|
|
|
1990
1995
|
const { verbose } = opts;
|
|
1991
1996
|
let sql = 'SELECT oid as "ID",\n pg_catalog.pg_get_userbyid(lomowner) as "Owner",\n ';
|
|
1992
1997
|
if (verbose) {
|
|
1993
|
-
sql += aclColumn(
|
|
1998
|
+
sql += aclColumn("lomacl") + ",\n ";
|
|
1994
1999
|
}
|
|
1995
2000
|
sql +=
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
return { sql, params: [], description:
|
|
2001
|
+
"pg_catalog.obj_description(oid, 'pg_largeobject') as \"Description\"\n" +
|
|
2002
|
+
"FROM pg_catalog.pg_largeobject_metadata\n" +
|
|
2003
|
+
"ORDER BY oid";
|
|
2004
|
+
return { sql, params: [], description: "Large objects" };
|
|
2000
2005
|
};
|
|
2001
2006
|
/* ------------------------------------------------------------------ */
|
|
2002
2007
|
/* \sf — show function definition */
|
|
@@ -2013,14 +2018,14 @@ export const showFunction = (opts) => {
|
|
|
2013
2018
|
// We emit a select returning the function definition by name; upstream
|
|
2014
2019
|
// psql resolves to oid then calls pg_get_functiondef(oid). Combine.
|
|
2015
2020
|
const sql = `SELECT pg_catalog.pg_get_functiondef('${opts.name.replace(/'/g, "''")}'::pg_catalog.regprocedure) AS def;`;
|
|
2016
|
-
return { sql, params: [], description:
|
|
2021
|
+
return { sql, params: [], description: "Function definition" };
|
|
2017
2022
|
};
|
|
2018
2023
|
/**
|
|
2019
2024
|
* Look up view definition for `\sv` / `\sv+`.
|
|
2020
2025
|
*/
|
|
2021
2026
|
export const showView = (opts) => {
|
|
2022
2027
|
const sql = `SELECT pg_catalog.pg_get_viewdef('${opts.name.replace(/'/g, "''")}'::pg_catalog.regclass, true) AS def;`;
|
|
2023
|
-
return { sql, params: [], description:
|
|
2028
|
+
return { sql, params: [], description: "View definition" };
|
|
2024
2029
|
};
|
|
2025
2030
|
/* ------------------------------------------------------------------ */
|
|
2026
2031
|
/* Per-relation follow-up queries used by describeOneTableDetails. */
|
|
@@ -2050,27 +2055,27 @@ export const fetchTableInfo = (opts) => {
|
|
|
2050
2055
|
const hasIsPart = serverAtLeast(serverVersion, PG_10);
|
|
2051
2056
|
const hasRelAm = serverAtLeast(serverVersion, PG_12);
|
|
2052
2057
|
const rowSec = hasRowSec
|
|
2053
|
-
?
|
|
2054
|
-
:
|
|
2055
|
-
const isPart = hasIsPart ?
|
|
2056
|
-
const amCol = hasRelAm ?
|
|
2057
|
-
const amName = hasRelAm ?
|
|
2058
|
+
? "c.relrowsecurity, c.relforcerowsecurity"
|
|
2059
|
+
: "false AS relrowsecurity, false AS relforcerowsecurity";
|
|
2060
|
+
const isPart = hasIsPart ? "c.relispartition" : "false AS relispartition";
|
|
2061
|
+
const amCol = hasRelAm ? "c.relam" : "0::oid AS relam";
|
|
2062
|
+
const amName = hasRelAm ? "am.amname" : "NULL::name AS amname";
|
|
2058
2063
|
const amJoin = hasRelAm
|
|
2059
|
-
?
|
|
2060
|
-
:
|
|
2061
|
-
const sql =
|
|
2064
|
+
? " LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam\n"
|
|
2065
|
+
: "";
|
|
2066
|
+
const sql = "SELECT " +
|
|
2062
2067
|
rowSec +
|
|
2063
|
-
|
|
2068
|
+
",\n c.relreplident,\n " +
|
|
2064
2069
|
isPart +
|
|
2065
|
-
|
|
2070
|
+
",\n c.reltablespace,\n " +
|
|
2066
2071
|
amCol +
|
|
2067
|
-
|
|
2072
|
+
",\n ts.spcname,\n " +
|
|
2068
2073
|
amName +
|
|
2069
|
-
|
|
2070
|
-
|
|
2074
|
+
"\nFROM pg_catalog.pg_class c\n" +
|
|
2075
|
+
" LEFT JOIN pg_catalog.pg_tablespace ts ON ts.oid = c.reltablespace\n" +
|
|
2071
2076
|
amJoin +
|
|
2072
2077
|
`WHERE c.oid = '${oid}';`;
|
|
2073
|
-
return { sql, params: [], description:
|
|
2078
|
+
return { sql, params: [], description: "Relation footer info" };
|
|
2074
2079
|
};
|
|
2075
2080
|
/**
|
|
2076
2081
|
* Named NOT NULL constraints (`pg_constraint.contype = 'n'`), introduced
|
|
@@ -2088,18 +2093,18 @@ export const fetchNotNullConstraints = (opts) => {
|
|
|
2088
2093
|
const { oid, serverVersion } = opts;
|
|
2089
2094
|
if (serverLess(serverVersion, PG_18)) {
|
|
2090
2095
|
return {
|
|
2091
|
-
sql:
|
|
2096
|
+
sql: "SELECT NULL::pg_catalog.text, NULL::pg_catalog.text, false, false WHERE false;",
|
|
2092
2097
|
params: [],
|
|
2093
|
-
description:
|
|
2098
|
+
description: "Not-null constraints",
|
|
2094
2099
|
};
|
|
2095
2100
|
}
|
|
2096
|
-
const sql =
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2101
|
+
const sql = "SELECT co.conname, at.attname, co.connoinherit, co.conislocal\n" +
|
|
2102
|
+
"FROM pg_catalog.pg_constraint co\n" +
|
|
2103
|
+
" JOIN pg_catalog.pg_attribute at\n" +
|
|
2104
|
+
" ON (at.attrelid = co.conrelid AND at.attnum = co.conkey[1])\n" +
|
|
2100
2105
|
`WHERE co.contype = 'n' AND co.conrelid = '${oid}'\n` +
|
|
2101
|
-
|
|
2102
|
-
return { sql, params: [], description:
|
|
2106
|
+
"ORDER BY at.attnum;";
|
|
2107
|
+
return { sql, params: [], description: "Not-null constraints" };
|
|
2103
2108
|
};
|
|
2104
2109
|
/**
|
|
2105
2110
|
* RLS policies for a relation. Output columns mirror upstream:
|
|
@@ -2112,23 +2117,23 @@ export const fetchNotNullConstraints = (opts) => {
|
|
|
2112
2117
|
export const fetchPolicies = (opts) => {
|
|
2113
2118
|
const { oid, serverVersion } = opts;
|
|
2114
2119
|
const permissive = serverAtLeast(serverVersion, PG_10)
|
|
2115
|
-
?
|
|
2120
|
+
? "pol.polpermissive"
|
|
2116
2121
|
: "'t' AS polpermissive";
|
|
2117
|
-
const sql =
|
|
2122
|
+
const sql = "SELECT pol.polname,\n " +
|
|
2118
2123
|
permissive +
|
|
2119
2124
|
",\n CASE WHEN pol.polroles = '{0}' THEN NULL ELSE pg_catalog.array_to_string(array(SELECT rolname FROM pg_catalog.pg_roles WHERE oid = ANY (pol.polroles) ORDER BY 1), ', ') END AS roles,\n" +
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2125
|
+
" pg_catalog.pg_get_expr(pol.polqual, pol.polrelid) AS qual,\n" +
|
|
2126
|
+
" pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid) AS withcheck,\n" +
|
|
2127
|
+
" CASE pol.polcmd\n" +
|
|
2123
2128
|
" WHEN 'r' THEN 'SELECT'\n" +
|
|
2124
2129
|
" WHEN 'a' THEN 'INSERT'\n" +
|
|
2125
2130
|
" WHEN 'w' THEN 'UPDATE'\n" +
|
|
2126
2131
|
" WHEN 'd' THEN 'DELETE'\n" +
|
|
2127
|
-
|
|
2128
|
-
|
|
2132
|
+
" END AS cmd\n" +
|
|
2133
|
+
"FROM pg_catalog.pg_policy pol\n" +
|
|
2129
2134
|
`WHERE pol.polrelid = '${oid}'\n` +
|
|
2130
|
-
|
|
2131
|
-
return { sql, params: [], description:
|
|
2135
|
+
"ORDER BY pol.polname;";
|
|
2136
|
+
return { sql, params: [], description: "Relation policies" };
|
|
2132
2137
|
};
|
|
2133
2138
|
/**
|
|
2134
2139
|
* Parents from `pg_inherits`. We exclude partitioned parents so
|
|
@@ -2138,12 +2143,12 @@ export const fetchPolicies = (opts) => {
|
|
|
2138
2143
|
*/
|
|
2139
2144
|
export const fetchInherits = (opts) => {
|
|
2140
2145
|
const { oid } = opts;
|
|
2141
|
-
const sql =
|
|
2142
|
-
|
|
2146
|
+
const sql = "SELECT c.oid::pg_catalog.regclass\n" +
|
|
2147
|
+
"FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n" +
|
|
2143
2148
|
`WHERE c.oid = i.inhparent AND i.inhrelid = '${oid}'\n` +
|
|
2144
2149
|
" AND c.relkind NOT IN ('p', 'I')\n" +
|
|
2145
|
-
|
|
2146
|
-
return { sql, params: [], description:
|
|
2150
|
+
"ORDER BY inhseqno;";
|
|
2151
|
+
return { sql, params: [], description: "Inherited-from relations" };
|
|
2147
2152
|
};
|
|
2148
2153
|
/**
|
|
2149
2154
|
* Child tables / partitions from `pg_inherits`. Output columns:
|
|
@@ -2157,23 +2162,23 @@ export const fetchInheritedBy = (opts) => {
|
|
|
2157
2162
|
const hasDetach = serverAtLeast(serverVersion, PG_14);
|
|
2158
2163
|
const hasPartBound = serverAtLeast(serverVersion, PG_10);
|
|
2159
2164
|
const detachCol = hasDetach
|
|
2160
|
-
?
|
|
2161
|
-
:
|
|
2165
|
+
? "i.inhdetachpending"
|
|
2166
|
+
: "false AS inhdetachpending";
|
|
2162
2167
|
const boundCol = hasPartBound
|
|
2163
|
-
?
|
|
2164
|
-
:
|
|
2168
|
+
? "pg_catalog.pg_get_expr(c.relpartbound, c.oid)"
|
|
2169
|
+
: "NULL::text";
|
|
2165
2170
|
const orderBy = hasPartBound
|
|
2166
2171
|
? "pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT'," +
|
|
2167
|
-
|
|
2168
|
-
:
|
|
2169
|
-
const sql =
|
|
2172
|
+
" c.oid::pg_catalog.regclass::pg_catalog.text"
|
|
2173
|
+
: "c.oid::pg_catalog.regclass::pg_catalog.text";
|
|
2174
|
+
const sql = "SELECT c.oid::pg_catalog.regclass, c.relkind,\n " +
|
|
2170
2175
|
detachCol +
|
|
2171
|
-
|
|
2176
|
+
",\n " +
|
|
2172
2177
|
boundCol +
|
|
2173
|
-
|
|
2178
|
+
"\nFROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n" +
|
|
2174
2179
|
`WHERE c.oid = i.inhrelid AND i.inhparent = '${oid}'\n` +
|
|
2175
2180
|
`ORDER BY ${orderBy};`;
|
|
2176
|
-
return { sql, params: [], description:
|
|
2181
|
+
return { sql, params: [], description: "Inheriting / child relations" };
|
|
2177
2182
|
};
|
|
2178
2183
|
/**
|
|
2179
2184
|
* Partition-of details for a child partition (`relispartition = true`).
|
|
@@ -2185,19 +2190,19 @@ export const fetchInheritedBy = (opts) => {
|
|
|
2185
2190
|
export const fetchPartitionOf = (opts) => {
|
|
2186
2191
|
const { oid, serverVersion, withConstraint } = opts;
|
|
2187
2192
|
const detachCol = serverAtLeast(serverVersion, PG_14)
|
|
2188
|
-
?
|
|
2189
|
-
:
|
|
2190
|
-
let sql =
|
|
2191
|
-
|
|
2193
|
+
? "i.inhdetachpending"
|
|
2194
|
+
: "false AS inhdetachpending";
|
|
2195
|
+
let sql = "SELECT inhparent::pg_catalog.regclass,\n" +
|
|
2196
|
+
" pg_catalog.pg_get_expr(c.relpartbound, c.oid),\n " +
|
|
2192
2197
|
detachCol;
|
|
2193
2198
|
if (withConstraint) {
|
|
2194
|
-
sql +=
|
|
2199
|
+
sql += ",\n pg_catalog.pg_get_partition_constraintdef(c.oid)";
|
|
2195
2200
|
}
|
|
2196
2201
|
sql +=
|
|
2197
|
-
|
|
2198
|
-
|
|
2202
|
+
"\nFROM pg_catalog.pg_class c\n" +
|
|
2203
|
+
" JOIN pg_catalog.pg_inherits i ON c.oid = i.inhrelid\n" +
|
|
2199
2204
|
`WHERE c.oid = '${oid}';`;
|
|
2200
|
-
return { sql, params: [], description:
|
|
2205
|
+
return { sql, params: [], description: "Partition-of details" };
|
|
2201
2206
|
};
|
|
2202
2207
|
/**
|
|
2203
2208
|
* Partition-key definition for a partitioned-table parent
|
|
@@ -2205,7 +2210,7 @@ export const fetchPartitionOf = (opts) => {
|
|
|
2205
2210
|
*/
|
|
2206
2211
|
export const fetchPartitionKey = (opts) => {
|
|
2207
2212
|
const sql = `SELECT pg_catalog.pg_get_partkeydef('${opts.oid}'::pg_catalog.oid);`;
|
|
2208
|
-
return { sql, params: [], description:
|
|
2213
|
+
return { sql, params: [], description: "Partition key" };
|
|
2209
2214
|
};
|
|
2210
2215
|
/**
|
|
2211
2216
|
* Foreign-table footer info: server name + ftoptions as a pre-formatted
|
|
@@ -2214,14 +2219,14 @@ export const fetchPartitionKey = (opts) => {
|
|
|
2214
2219
|
*/
|
|
2215
2220
|
export const fetchForeignTableInfo = (opts) => {
|
|
2216
2221
|
const { oid } = opts;
|
|
2217
|
-
const sql =
|
|
2218
|
-
|
|
2222
|
+
const sql = "SELECT s.srvname,\n" +
|
|
2223
|
+
" pg_catalog.array_to_string(ARRAY(\n" +
|
|
2219
2224
|
" SELECT pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value)\n" +
|
|
2220
2225
|
" FROM pg_catalog.pg_options_to_table(ftoptions)), ', ') AS ftoptions\n" +
|
|
2221
|
-
|
|
2222
|
-
|
|
2226
|
+
"FROM pg_catalog.pg_foreign_table f,\n" +
|
|
2227
|
+
" pg_catalog.pg_foreign_server s\n" +
|
|
2223
2228
|
`WHERE f.ftrelid = '${oid}' AND s.oid = f.ftserver;`;
|
|
2224
|
-
return { sql, params: [], description:
|
|
2229
|
+
return { sql, params: [], description: "Foreign-table footer info" };
|
|
2225
2230
|
};
|
|
2226
2231
|
/**
|
|
2227
2232
|
* Pull `indexrelid::regclass` for the index marked as REPLICA IDENTITY
|
|
@@ -2229,12 +2234,12 @@ export const fetchForeignTableInfo = (opts) => {
|
|
|
2229
2234
|
*/
|
|
2230
2235
|
export const fetchReplicaIdentityIndex = (opts) => {
|
|
2231
2236
|
const { oid } = opts;
|
|
2232
|
-
const sql =
|
|
2233
|
-
|
|
2234
|
-
|
|
2237
|
+
const sql = "SELECT c2.relname\n" +
|
|
2238
|
+
"FROM pg_catalog.pg_index i\n" +
|
|
2239
|
+
" JOIN pg_catalog.pg_class c2 ON c2.oid = i.indexrelid\n" +
|
|
2235
2240
|
`WHERE i.indrelid = '${oid}' AND i.indisreplident\n` +
|
|
2236
|
-
|
|
2237
|
-
return { sql, params: [], description:
|
|
2241
|
+
"LIMIT 1;";
|
|
2242
|
+
return { sql, params: [], description: "Replica-identity index" };
|
|
2238
2243
|
};
|
|
2239
2244
|
/**
|
|
2240
2245
|
* Extended-statistics objects defined on a relation. Mirrors the upstream
|
|
@@ -2250,34 +2255,34 @@ export const fetchStatisticsObjects = (opts) => {
|
|
|
2250
2255
|
const { oid, serverVersion } = opts;
|
|
2251
2256
|
if (serverLess(serverVersion, PG_10)) {
|
|
2252
2257
|
return {
|
|
2253
|
-
sql:
|
|
2258
|
+
sql: "/* server < 10 does not support extended statistics */ SELECT 1 WHERE false;",
|
|
2254
2259
|
params: [],
|
|
2255
|
-
description:
|
|
2260
|
+
description: "Statistics objects",
|
|
2256
2261
|
};
|
|
2257
2262
|
}
|
|
2258
2263
|
// `pg_get_statisticsobjdef_columns` was added in PG 14. Older servers
|
|
2259
2264
|
// reconstruct the column list from `pg_statistic_ext.stxkeys`.
|
|
2260
2265
|
const columnsExpr = serverAtLeast(serverVersion, PG_14)
|
|
2261
|
-
?
|
|
2266
|
+
? "pg_catalog.pg_get_statisticsobjdef_columns(es.oid)"
|
|
2262
2267
|
: "(SELECT pg_catalog.string_agg(pg_catalog.quote_ident(a.attname), ', ')\n" +
|
|
2263
|
-
|
|
2264
|
-
|
|
2268
|
+
" FROM pg_catalog.unnest(es.stxkeys) k(attnum)\n" +
|
|
2269
|
+
" JOIN pg_catalog.pg_attribute a ON a.attrelid = es.stxrelid AND a.attnum = k.attnum AND NOT a.attisdropped)";
|
|
2265
2270
|
// `pg_statistic_ext.stxstattarget` exists on every supported PG; PG 17
|
|
2266
2271
|
// changed its type from int4 to int2 but we just CAST to text.
|
|
2267
|
-
const sql =
|
|
2268
|
-
|
|
2272
|
+
const sql = "SELECT es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS stxnsp,\n" +
|
|
2273
|
+
" es.stxname,\n" +
|
|
2269
2274
|
" 'd' = any(es.stxkind) AS ndist_enabled,\n" +
|
|
2270
2275
|
" 'f' = any(es.stxkind) AS deps_enabled,\n" +
|
|
2271
2276
|
" 'm' = any(es.stxkind) AS mcv_enabled,\n" +
|
|
2272
|
-
|
|
2277
|
+
" " +
|
|
2273
2278
|
columnsExpr +
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2279
|
+
" AS columns,\n" +
|
|
2280
|
+
" es.stxrelid::pg_catalog.regclass::pg_catalog.text AS stxrelname,\n" +
|
|
2281
|
+
" es.stxstattarget\n" +
|
|
2282
|
+
"FROM pg_catalog.pg_statistic_ext es\n" +
|
|
2278
2283
|
`WHERE es.stxrelid = '${oid}'\n` +
|
|
2279
|
-
|
|
2280
|
-
return { sql, params: [], description:
|
|
2284
|
+
"ORDER BY stxnsp, es.stxname;";
|
|
2285
|
+
return { sql, params: [], description: "Statistics objects" };
|
|
2281
2286
|
};
|
|
2282
2287
|
/**
|
|
2283
2288
|
* Publications a relation belongs to. Returns one column `pubname` per
|
|
@@ -2292,29 +2297,29 @@ export const fetchTablePublications = (opts) => {
|
|
|
2292
2297
|
const { oid, serverVersion } = opts;
|
|
2293
2298
|
if (serverLess(serverVersion, PG_10)) {
|
|
2294
2299
|
return {
|
|
2295
|
-
sql:
|
|
2300
|
+
sql: "/* server < 10 does not support publications */ SELECT 1 WHERE false;",
|
|
2296
2301
|
params: [],
|
|
2297
|
-
description:
|
|
2302
|
+
description: "Table publications",
|
|
2298
2303
|
};
|
|
2299
2304
|
}
|
|
2300
2305
|
const hasPubNs = serverAtLeast(serverVersion, PG_15);
|
|
2301
|
-
let sql =
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
+
let sql = "SELECT pub.pubname\n" +
|
|
2307
|
+
"FROM pg_catalog.pg_publication pub\n" +
|
|
2308
|
+
"WHERE pub.puballtables\n" +
|
|
2309
|
+
" OR EXISTS (\n" +
|
|
2310
|
+
" SELECT 1 FROM pg_catalog.pg_publication_rel pr\n" +
|
|
2306
2311
|
` WHERE pr.prpubid = pub.oid AND pr.prrelid = '${oid}'\n` +
|
|
2307
|
-
|
|
2312
|
+
" )";
|
|
2308
2313
|
if (hasPubNs) {
|
|
2309
2314
|
sql +=
|
|
2310
|
-
|
|
2311
|
-
|
|
2315
|
+
"\n OR EXISTS (\n" +
|
|
2316
|
+
" SELECT 1 FROM pg_catalog.pg_publication_namespace pn\n" +
|
|
2312
2317
|
` JOIN pg_catalog.pg_class c ON c.oid = '${oid}'\n` +
|
|
2313
|
-
|
|
2314
|
-
|
|
2318
|
+
" WHERE pn.pnpubid = pub.oid AND pn.pnnspid = c.relnamespace\n" +
|
|
2319
|
+
" )";
|
|
2315
2320
|
}
|
|
2316
|
-
sql +=
|
|
2317
|
-
return { sql, params: [], description:
|
|
2321
|
+
sql += "\nORDER BY 1;";
|
|
2322
|
+
return { sql, params: [], description: "Table publications" };
|
|
2318
2323
|
};
|
|
2319
2324
|
/**
|
|
2320
2325
|
* Subscriptions that include this relation. Mirrors the upstream
|
|
@@ -2328,17 +2333,17 @@ export const fetchTableSubscriptions = (opts) => {
|
|
|
2328
2333
|
const { oid, serverVersion } = opts;
|
|
2329
2334
|
if (serverLess(serverVersion, PG_10)) {
|
|
2330
2335
|
return {
|
|
2331
|
-
sql:
|
|
2336
|
+
sql: "/* server < 10 does not support subscriptions */ SELECT 1 WHERE false;",
|
|
2332
2337
|
params: [],
|
|
2333
|
-
description:
|
|
2338
|
+
description: "Table subscriptions",
|
|
2334
2339
|
};
|
|
2335
2340
|
}
|
|
2336
|
-
const sql =
|
|
2337
|
-
|
|
2338
|
-
|
|
2341
|
+
const sql = "SELECT sub.subname\n" +
|
|
2342
|
+
"FROM pg_catalog.pg_subscription sub\n" +
|
|
2343
|
+
"JOIN pg_catalog.pg_subscription_rel sr ON sr.srsubid = sub.oid\n" +
|
|
2339
2344
|
`WHERE sr.srrelid = '${oid}'\n` +
|
|
2340
|
-
|
|
2341
|
-
return { sql, params: [], description:
|
|
2345
|
+
"ORDER BY 1;";
|
|
2346
|
+
return { sql, params: [], description: "Table subscriptions" };
|
|
2342
2347
|
};
|
|
2343
2348
|
/**
|
|
2344
2349
|
* Per-column FDW options for a foreign table. Returns one row per column
|
|
@@ -2349,15 +2354,15 @@ export const fetchTableSubscriptions = (opts) => {
|
|
|
2349
2354
|
*/
|
|
2350
2355
|
export const fetchPerColumnFdwOptions = (opts) => {
|
|
2351
2356
|
const { oid } = opts;
|
|
2352
|
-
const sql =
|
|
2353
|
-
|
|
2357
|
+
const sql = "SELECT a.attname,\n" +
|
|
2358
|
+
" pg_catalog.array_to_string(ARRAY(\n" +
|
|
2354
2359
|
" SELECT pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value)\n" +
|
|
2355
2360
|
" FROM pg_catalog.pg_options_to_table(a.attfdwoptions)), ', ') AS opts\n" +
|
|
2356
|
-
|
|
2361
|
+
"FROM pg_catalog.pg_attribute a\n" +
|
|
2357
2362
|
`WHERE a.attrelid = '${oid}' AND a.attnum > 0 AND NOT a.attisdropped\n` +
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
return { sql, params: [], description:
|
|
2363
|
+
" AND a.attfdwoptions IS NOT NULL\n" +
|
|
2364
|
+
"ORDER BY a.attnum;";
|
|
2365
|
+
return { sql, params: [], description: "Per-column FDW options" };
|
|
2361
2366
|
};
|
|
2362
2367
|
/**
|
|
2363
2368
|
* For a TOAST table (`relkind = 't'`), look up the owning user table.
|
|
@@ -2365,9 +2370,9 @@ export const fetchPerColumnFdwOptions = (opts) => {
|
|
|
2365
2370
|
*/
|
|
2366
2371
|
export const fetchToastOwningTable = (opts) => {
|
|
2367
2372
|
const { oid } = opts;
|
|
2368
|
-
const sql =
|
|
2369
|
-
|
|
2373
|
+
const sql = "SELECT oid::pg_catalog.regclass::pg_catalog.text AS relname\n" +
|
|
2374
|
+
"FROM pg_catalog.pg_class\n" +
|
|
2370
2375
|
`WHERE reltoastrelid = '${oid}'\n` +
|
|
2371
|
-
|
|
2372
|
-
return { sql, params: [], description:
|
|
2376
|
+
"LIMIT 1;";
|
|
2377
|
+
return { sql, params: [], description: "TOAST owning table" };
|
|
2373
2378
|
};
|