neonctl 2.22.2 → 2.23.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 +84 -0
- package/analytics.js +5 -2
- package/commands/branches.js +9 -1
- package/commands/connection_string.js +9 -1
- package/commands/functions.js +277 -0
- package/commands/index.js +4 -0
- package/commands/neon_auth.js +1013 -0
- package/commands/projects.js +9 -1
- package/commands/psql.js +6 -1
- package/functions_api.js +44 -0
- package/package.json +15 -5
- package/psql/cli.js +51 -0
- package/psql/command/cmd_cond.js +437 -0
- package/psql/command/cmd_connect.js +815 -0
- package/psql/command/cmd_copy.js +1025 -0
- package/psql/command/cmd_describe.js +1810 -0
- package/psql/command/cmd_format.js +909 -0
- package/psql/command/cmd_io.js +2187 -0
- package/psql/command/cmd_lo.js +385 -0
- package/psql/command/cmd_meta.js +970 -0
- package/psql/command/cmd_misc.js +187 -0
- package/psql/command/cmd_pipeline.js +1141 -0
- package/psql/command/cmd_restrict.js +171 -0
- package/psql/command/cmd_show.js +751 -0
- package/psql/command/dispatch.js +343 -0
- package/psql/command/inputQueue.js +42 -0
- package/psql/command/shared.js +71 -0
- package/psql/complete/filenames.js +139 -0
- package/psql/complete/index.js +104 -0
- package/psql/complete/matcher.js +314 -0
- package/psql/complete/psqlVars.js +247 -0
- package/psql/complete/queries.js +491 -0
- package/psql/complete/rules.js +2387 -0
- package/psql/core/common.js +1250 -0
- package/psql/core/help.js +576 -0
- package/psql/core/mainloop.js +1353 -0
- package/psql/core/prompt.js +437 -0
- package/psql/core/settings.js +684 -0
- package/psql/core/sqlHelp.js +1066 -0
- package/psql/core/startup.js +840 -0
- package/psql/core/syncVars.js +116 -0
- package/psql/core/variables.js +287 -0
- package/psql/describe/formatters.js +1277 -0
- package/psql/describe/processNamePattern.js +270 -0
- package/psql/describe/queries.js +2373 -0
- package/psql/describe/versionGate.js +43 -0
- package/psql/index.js +2005 -0
- package/psql/io/history.js +299 -0
- package/psql/io/input.js +120 -0
- package/psql/io/lineEditor/buffer.js +323 -0
- package/psql/io/lineEditor/complete.js +227 -0
- package/psql/io/lineEditor/filename.js +159 -0
- package/psql/io/lineEditor/index.js +891 -0
- package/psql/io/lineEditor/keymap.js +738 -0
- package/psql/io/lineEditor/vt100.js +363 -0
- package/psql/io/pgpass.js +202 -0
- package/psql/io/pgservice.js +194 -0
- package/psql/io/psqlrc.js +422 -0
- package/psql/print/aligned.js +1756 -0
- package/psql/print/asciidoc.js +248 -0
- package/psql/print/crosstab.js +460 -0
- package/psql/print/csv.js +92 -0
- package/psql/print/html.js +258 -0
- package/psql/print/json.js +96 -0
- package/psql/print/latex.js +396 -0
- package/psql/print/pager.js +265 -0
- package/psql/print/troff.js +258 -0
- package/psql/print/unaligned.js +118 -0
- package/psql/print/units.js +135 -0
- package/psql/scanner/slash.js +513 -0
- package/psql/scanner/sql.js +910 -0
- package/psql/scanner/stringutils.js +390 -0
- package/psql/types/backslash.js +1 -0
- package/psql/types/connection.js +1 -0
- package/psql/types/index.js +7 -0
- package/psql/types/printer.js +1 -0
- package/psql/types/repl.js +1 -0
- package/psql/types/scanner.js +24 -0
- package/psql/types/settings.js +1 -0
- package/psql/types/variables.js +1 -0
- package/psql/wire/connection.js +2844 -0
- package/psql/wire/copy.js +108 -0
- package/psql/wire/notify.js +59 -0
- package/psql/wire/pipeline.js +519 -0
- package/psql/wire/protocol.js +466 -0
- package/psql/wire/sasl.js +296 -0
- package/psql/wire/tls.js +596 -0
- package/test_utils/fixtures.js +1 -0
- package/utils/esbuild.js +147 -0
- package/utils/psql.js +107 -11
- package/utils/zip.js +4 -0
- package/writer.js +1 -1
- package/commands/auth.test.js +0 -211
- package/commands/branches.test.js +0 -460
- package/commands/checkout.test.js +0 -170
- package/commands/connection_string.test.js +0 -196
- package/commands/data_api.test.js +0 -169
- package/commands/databases.test.js +0 -39
- package/commands/help.test.js +0 -9
- package/commands/init.test.js +0 -56
- package/commands/ip_allow.test.js +0 -59
- package/commands/link.test.js +0 -381
- package/commands/operations.test.js +0 -7
- package/commands/orgs.test.js +0 -7
- package/commands/projects.test.js +0 -144
- package/commands/psql.test.js +0 -49
- package/commands/roles.test.js +0 -37
- package/commands/set_context.test.js +0 -159
- package/commands/vpc_endpoints.test.js +0 -69
- package/context.test.js +0 -119
- package/env.test.js +0 -55
- package/utils/formats.test.js +0 -32
- package/writer.test.js +0 -104
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog-query templates for tab completion.
|
|
3
|
+
*
|
|
4
|
+
* Each template returns a single column of completion candidates and takes
|
|
5
|
+
* one parameter — the LIKE pattern (i.e. the user's partial prefix with a
|
|
6
|
+
* trailing `%`). We use `pg_catalog.quote_ident()` so identifiers that need
|
|
7
|
+
* quoting come back already wrapped in `"..."`.
|
|
8
|
+
*
|
|
9
|
+
* The templates are intentionally narrow: psql's upstream tab-complete uses
|
|
10
|
+
* elaborate `SchemaQuery` structs that synthesize visibility predicates
|
|
11
|
+
* (search-path awareness) at runtime. We trade that nuance for portability
|
|
12
|
+
* — these queries just `LIKE` against the system catalogs and let the user
|
|
13
|
+
* see everything they have access to, sorted alphabetically.
|
|
14
|
+
*
|
|
15
|
+
* Every query takes a single `$1` parameter (the LIKE pattern) and is
|
|
16
|
+
* capped at 1000 rows so a wildcard `%` doesn't dump entire databases.
|
|
17
|
+
*/
|
|
18
|
+
const LIMIT = 1000;
|
|
19
|
+
/** Tables (incl. partitioned tables). */
|
|
20
|
+
export const Query_for_list_of_tables = `
|
|
21
|
+
SELECT pg_catalog.quote_ident(c.relname)
|
|
22
|
+
FROM pg_catalog.pg_class c
|
|
23
|
+
WHERE c.relkind IN ('r','p')
|
|
24
|
+
AND c.relname ILIKE $1
|
|
25
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
26
|
+
ORDER BY 1
|
|
27
|
+
LIMIT ${LIMIT}
|
|
28
|
+
`;
|
|
29
|
+
/** Views. */
|
|
30
|
+
export const Query_for_list_of_views = `
|
|
31
|
+
SELECT pg_catalog.quote_ident(c.relname)
|
|
32
|
+
FROM pg_catalog.pg_class c
|
|
33
|
+
WHERE c.relkind = 'v'
|
|
34
|
+
AND c.relname ILIKE $1
|
|
35
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
36
|
+
ORDER BY 1
|
|
37
|
+
LIMIT ${LIMIT}
|
|
38
|
+
`;
|
|
39
|
+
/** Materialized views. */
|
|
40
|
+
export const Query_for_list_of_matviews = `
|
|
41
|
+
SELECT pg_catalog.quote_ident(c.relname)
|
|
42
|
+
FROM pg_catalog.pg_class c
|
|
43
|
+
WHERE c.relkind = 'm'
|
|
44
|
+
AND c.relname ILIKE $1
|
|
45
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
46
|
+
ORDER BY 1
|
|
47
|
+
LIMIT ${LIMIT}
|
|
48
|
+
`;
|
|
49
|
+
/** Sequences. */
|
|
50
|
+
export const Query_for_list_of_sequences = `
|
|
51
|
+
SELECT pg_catalog.quote_ident(c.relname)
|
|
52
|
+
FROM pg_catalog.pg_class c
|
|
53
|
+
WHERE c.relkind = 'S'
|
|
54
|
+
AND c.relname ILIKE $1
|
|
55
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
56
|
+
ORDER BY 1
|
|
57
|
+
LIMIT ${LIMIT}
|
|
58
|
+
`;
|
|
59
|
+
/** Indexes. */
|
|
60
|
+
export const Query_for_list_of_indexes = `
|
|
61
|
+
SELECT pg_catalog.quote_ident(c.relname)
|
|
62
|
+
FROM pg_catalog.pg_class c
|
|
63
|
+
WHERE c.relkind IN ('i','I')
|
|
64
|
+
AND c.relname ILIKE $1
|
|
65
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
66
|
+
ORDER BY 1
|
|
67
|
+
LIMIT ${LIMIT}
|
|
68
|
+
`;
|
|
69
|
+
/** Foreign tables. */
|
|
70
|
+
export const Query_for_list_of_foreign_tables = `
|
|
71
|
+
SELECT pg_catalog.quote_ident(c.relname)
|
|
72
|
+
FROM pg_catalog.pg_class c
|
|
73
|
+
WHERE c.relkind = 'f'
|
|
74
|
+
AND c.relname ILIKE $1
|
|
75
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
76
|
+
ORDER BY 1
|
|
77
|
+
LIMIT ${LIMIT}
|
|
78
|
+
`;
|
|
79
|
+
/** Any relation (tables, views, mviews, indexes, sequences, foreign tables). */
|
|
80
|
+
export const Query_for_list_of_relations = `
|
|
81
|
+
SELECT pg_catalog.quote_ident(c.relname)
|
|
82
|
+
FROM pg_catalog.pg_class c
|
|
83
|
+
WHERE c.relkind IN ('r','v','m','S','f','p')
|
|
84
|
+
AND c.relname ILIKE $1
|
|
85
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
86
|
+
ORDER BY 1
|
|
87
|
+
LIMIT ${LIMIT}
|
|
88
|
+
`;
|
|
89
|
+
/** Tables + views + matviews (what FROM/UPDATE/INSERT INTO accept). */
|
|
90
|
+
export const Query_for_list_of_tables_views = `
|
|
91
|
+
SELECT pg_catalog.quote_ident(c.relname)
|
|
92
|
+
FROM pg_catalog.pg_class c
|
|
93
|
+
WHERE c.relkind IN ('r','v','m','p','f')
|
|
94
|
+
AND c.relname ILIKE $1
|
|
95
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
96
|
+
ORDER BY 1
|
|
97
|
+
LIMIT ${LIMIT}
|
|
98
|
+
`;
|
|
99
|
+
/** Schemas. */
|
|
100
|
+
export const Query_for_list_of_schemas = `
|
|
101
|
+
SELECT pg_catalog.quote_ident(nspname)
|
|
102
|
+
FROM pg_catalog.pg_namespace
|
|
103
|
+
WHERE nspname ILIKE $1
|
|
104
|
+
ORDER BY 1
|
|
105
|
+
LIMIT ${LIMIT}
|
|
106
|
+
`;
|
|
107
|
+
/** Functions (not procedures). */
|
|
108
|
+
export const Query_for_list_of_functions = `
|
|
109
|
+
SELECT pg_catalog.quote_ident(p.proname)
|
|
110
|
+
FROM pg_catalog.pg_proc p
|
|
111
|
+
WHERE p.proname ILIKE $1
|
|
112
|
+
AND pg_catalog.pg_function_is_visible(p.oid)
|
|
113
|
+
ORDER BY 1
|
|
114
|
+
LIMIT ${LIMIT}
|
|
115
|
+
`;
|
|
116
|
+
/** Roles. */
|
|
117
|
+
export const Query_for_list_of_roles = `
|
|
118
|
+
SELECT pg_catalog.quote_ident(rolname)
|
|
119
|
+
FROM pg_catalog.pg_roles
|
|
120
|
+
WHERE rolname ILIKE $1
|
|
121
|
+
ORDER BY 1
|
|
122
|
+
LIMIT ${LIMIT}
|
|
123
|
+
`;
|
|
124
|
+
/** Extensions. */
|
|
125
|
+
export const Query_for_list_of_extensions = `
|
|
126
|
+
SELECT pg_catalog.quote_ident(extname)
|
|
127
|
+
FROM pg_catalog.pg_extension
|
|
128
|
+
WHERE extname ILIKE $1
|
|
129
|
+
ORDER BY 1
|
|
130
|
+
LIMIT ${LIMIT}
|
|
131
|
+
`;
|
|
132
|
+
/** Available extensions (installable). */
|
|
133
|
+
export const Query_for_list_of_available_extensions = `
|
|
134
|
+
SELECT pg_catalog.quote_ident(name)
|
|
135
|
+
FROM pg_catalog.pg_available_extensions
|
|
136
|
+
WHERE name ILIKE $1
|
|
137
|
+
ORDER BY 1
|
|
138
|
+
LIMIT ${LIMIT}
|
|
139
|
+
`;
|
|
140
|
+
/** Databases. */
|
|
141
|
+
export const Query_for_list_of_databases = `
|
|
142
|
+
SELECT pg_catalog.quote_ident(datname)
|
|
143
|
+
FROM pg_catalog.pg_database
|
|
144
|
+
WHERE datname ILIKE $1
|
|
145
|
+
ORDER BY 1
|
|
146
|
+
LIMIT ${LIMIT}
|
|
147
|
+
`;
|
|
148
|
+
/** Types. */
|
|
149
|
+
export const Query_for_list_of_types = `
|
|
150
|
+
SELECT pg_catalog.quote_ident(t.typname)
|
|
151
|
+
FROM pg_catalog.pg_type t
|
|
152
|
+
WHERE (t.typrelid = 0 OR
|
|
153
|
+
(SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid))
|
|
154
|
+
AND t.typname NOT LIKE E'\\\\_%'
|
|
155
|
+
AND t.typname ILIKE $1
|
|
156
|
+
AND pg_catalog.pg_type_is_visible(t.oid)
|
|
157
|
+
ORDER BY 1
|
|
158
|
+
LIMIT ${LIMIT}
|
|
159
|
+
`;
|
|
160
|
+
/** Languages. */
|
|
161
|
+
export const Query_for_list_of_languages = `
|
|
162
|
+
SELECT pg_catalog.quote_ident(lanname)
|
|
163
|
+
FROM pg_catalog.pg_language
|
|
164
|
+
WHERE lanname != 'internal'
|
|
165
|
+
AND lanname ILIKE $1
|
|
166
|
+
ORDER BY 1
|
|
167
|
+
LIMIT ${LIMIT}
|
|
168
|
+
`;
|
|
169
|
+
/** Tablespaces. */
|
|
170
|
+
export const Query_for_list_of_tablespaces = `
|
|
171
|
+
SELECT pg_catalog.quote_ident(spcname)
|
|
172
|
+
FROM pg_catalog.pg_tablespace
|
|
173
|
+
WHERE spcname ILIKE $1
|
|
174
|
+
ORDER BY 1
|
|
175
|
+
LIMIT ${LIMIT}
|
|
176
|
+
`;
|
|
177
|
+
/** Operators. */
|
|
178
|
+
export const Query_for_list_of_operators = `
|
|
179
|
+
SELECT pg_catalog.quote_ident(o.oprname)
|
|
180
|
+
FROM pg_catalog.pg_operator o
|
|
181
|
+
WHERE o.oprname ILIKE $1
|
|
182
|
+
AND pg_catalog.pg_operator_is_visible(o.oid)
|
|
183
|
+
ORDER BY 1
|
|
184
|
+
LIMIT ${LIMIT}
|
|
185
|
+
`;
|
|
186
|
+
/** Casts (no quoting; format is "type AS type" — used rarely). */
|
|
187
|
+
export const Query_for_list_of_casts = `
|
|
188
|
+
SELECT pg_catalog.format_type(castsource, NULL)
|
|
189
|
+
|| ' AS '
|
|
190
|
+
|| pg_catalog.format_type(casttarget, NULL) AS cast
|
|
191
|
+
FROM pg_catalog.pg_cast
|
|
192
|
+
WHERE pg_catalog.format_type(castsource, NULL)
|
|
193
|
+
|| ' AS '
|
|
194
|
+
|| pg_catalog.format_type(casttarget, NULL) ILIKE $1
|
|
195
|
+
ORDER BY 1
|
|
196
|
+
LIMIT ${LIMIT}
|
|
197
|
+
`;
|
|
198
|
+
/** Configuration parameter (GUC) names — `pg_settings`. */
|
|
199
|
+
export const Query_for_list_of_set_vars = `
|
|
200
|
+
SELECT pg_catalog.lower(name)
|
|
201
|
+
FROM pg_catalog.pg_settings
|
|
202
|
+
WHERE name ILIKE $1
|
|
203
|
+
ORDER BY 1
|
|
204
|
+
LIMIT ${LIMIT}
|
|
205
|
+
`;
|
|
206
|
+
/**
|
|
207
|
+
* Allowed values of an enum-typed GUC — `pg_settings.enumvals`.
|
|
208
|
+
*
|
|
209
|
+
* The GUC name is the first parameter (matched case-insensitively against
|
|
210
|
+
* `pg_settings.name`, since names like `IntervalStyle` appear mixed-case in
|
|
211
|
+
* the catalog but are addressed in lowercase from user input). The ILIKE
|
|
212
|
+
* prefix on the unnested values is the trailing parameter.
|
|
213
|
+
*
|
|
214
|
+
* Mirrors upstream `tab-complete.in.c`'s `Query_for_values_of_enum_GUC`. The
|
|
215
|
+
* catalog stores enum values in lowercase (e.g. `iso_8601`, `use_column`),
|
|
216
|
+
* which matches how `SET <name> TO <value>` expects them.
|
|
217
|
+
*/
|
|
218
|
+
export const Query_for_values_of_enum_GUC = `
|
|
219
|
+
SELECT val
|
|
220
|
+
FROM (
|
|
221
|
+
SELECT pg_catalog.unnest(enumvals) AS val
|
|
222
|
+
FROM pg_catalog.pg_settings
|
|
223
|
+
WHERE pg_catalog.lower(name) = pg_catalog.lower($1)
|
|
224
|
+
AND enumvals IS NOT NULL
|
|
225
|
+
) sub
|
|
226
|
+
WHERE val ILIKE $2
|
|
227
|
+
ORDER BY 1
|
|
228
|
+
LIMIT ${LIMIT}
|
|
229
|
+
`;
|
|
230
|
+
/** Access methods (index AMs primarily). */
|
|
231
|
+
export const Query_for_list_of_access_methods = `
|
|
232
|
+
SELECT pg_catalog.quote_ident(amname)
|
|
233
|
+
FROM pg_catalog.pg_am
|
|
234
|
+
WHERE amname ILIKE $1
|
|
235
|
+
ORDER BY 1
|
|
236
|
+
LIMIT ${LIMIT}
|
|
237
|
+
`;
|
|
238
|
+
/** Index access methods only (`amtype = 'i'`). */
|
|
239
|
+
export const Query_for_list_of_index_access_methods = `
|
|
240
|
+
SELECT pg_catalog.quote_ident(amname)
|
|
241
|
+
FROM pg_catalog.pg_am
|
|
242
|
+
WHERE amname ILIKE $1
|
|
243
|
+
AND amtype = 'i'
|
|
244
|
+
ORDER BY 1
|
|
245
|
+
LIMIT ${LIMIT}
|
|
246
|
+
`;
|
|
247
|
+
/** Built-in type names — for CREATE TABLE column-type completion. */
|
|
248
|
+
export const Query_for_list_of_datatypes = `
|
|
249
|
+
SELECT pg_catalog.format_type(t.oid, NULL)
|
|
250
|
+
FROM pg_catalog.pg_type t
|
|
251
|
+
WHERE (t.typrelid = 0 OR
|
|
252
|
+
(SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid))
|
|
253
|
+
AND NOT EXISTS (
|
|
254
|
+
SELECT 1 FROM pg_catalog.pg_type el
|
|
255
|
+
WHERE el.typarray = t.oid
|
|
256
|
+
)
|
|
257
|
+
AND pg_catalog.format_type(t.oid, NULL) ILIKE $1
|
|
258
|
+
AND pg_catalog.pg_type_is_visible(t.oid)
|
|
259
|
+
ORDER BY 1
|
|
260
|
+
LIMIT ${LIMIT}
|
|
261
|
+
`;
|
|
262
|
+
/** Publications. */
|
|
263
|
+
export const Query_for_list_of_publications = `
|
|
264
|
+
SELECT pg_catalog.quote_ident(pubname)
|
|
265
|
+
FROM pg_catalog.pg_publication
|
|
266
|
+
WHERE pubname ILIKE $1
|
|
267
|
+
ORDER BY 1
|
|
268
|
+
LIMIT ${LIMIT}
|
|
269
|
+
`;
|
|
270
|
+
/** Subscriptions. */
|
|
271
|
+
export const Query_for_list_of_subscriptions = `
|
|
272
|
+
SELECT pg_catalog.quote_ident(subname)
|
|
273
|
+
FROM pg_catalog.pg_subscription
|
|
274
|
+
WHERE subname ILIKE $1
|
|
275
|
+
ORDER BY 1
|
|
276
|
+
LIMIT ${LIMIT}
|
|
277
|
+
`;
|
|
278
|
+
/**
|
|
279
|
+
* Relations qualified by an explicit schema. The caller passes the schema
|
|
280
|
+
* name as $1 and the ILIKE prefix as $2 — this lets `SELECT * FROM pg_catalog.x`
|
|
281
|
+
* complete to `pg_catalog.xxxx`. The schema name is matched
|
|
282
|
+
* case-insensitively so `PUBLIC.t` resolves to relations in `public`.
|
|
283
|
+
*
|
|
284
|
+
* Note: deliberately excludes `relkind = 'i'` (indexes) so that
|
|
285
|
+
* `SELECT * FROM public.tab<tab>` doesn't include `tab1_pkey` alongside
|
|
286
|
+
* `tab1`. Index-qualifying completions (REINDEX, DROP INDEX, ALTER INDEX)
|
|
287
|
+
* have their own table-kind queries and don't route through this helper.
|
|
288
|
+
*/
|
|
289
|
+
export const Query_for_list_of_relations_in_schema = `
|
|
290
|
+
SELECT pg_catalog.quote_ident(c.relname)
|
|
291
|
+
FROM pg_catalog.pg_class c
|
|
292
|
+
JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
|
|
293
|
+
WHERE c.relkind IN ('r','v','m','S','f','p')
|
|
294
|
+
AND pg_catalog.lower(n.nspname) = pg_catalog.lower($1)
|
|
295
|
+
AND c.relname ILIKE $2
|
|
296
|
+
ORDER BY 1
|
|
297
|
+
LIMIT ${LIMIT}
|
|
298
|
+
`;
|
|
299
|
+
/**
|
|
300
|
+
* Constraint names attached to a referenced table. Mirrors upstream's
|
|
301
|
+
* `Query_for_constraint_of_table` (tab-complete.in.c ~line 453), which
|
|
302
|
+
* joins `pg_constraint` to `pg_class` via `conrelid` and filters by the
|
|
303
|
+
* referenced table name.
|
|
304
|
+
*
|
|
305
|
+
* Caller passes `[refName]` (the table the user typed between
|
|
306
|
+
* `ALTER TABLE` and `DROP CONSTRAINT`, already case-folded for unquoted
|
|
307
|
+
* input — see `parseTableRef` in rules.ts) and the ILIKE prefix.
|
|
308
|
+
*
|
|
309
|
+
* Visibility is checked via `pg_table_is_visible(c.oid)` so the user's
|
|
310
|
+
* `search_path` controls which schema's `tab1` is matched when the user
|
|
311
|
+
* gives an unqualified reference.
|
|
312
|
+
*/
|
|
313
|
+
export const Query_for_constraint_of_table = `
|
|
314
|
+
SELECT pg_catalog.quote_ident(con.conname)
|
|
315
|
+
FROM pg_catalog.pg_constraint con, pg_catalog.pg_class c
|
|
316
|
+
WHERE con.conrelid = c.oid
|
|
317
|
+
AND c.relname = $1
|
|
318
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
319
|
+
AND con.conname ILIKE $2
|
|
320
|
+
ORDER BY 1
|
|
321
|
+
LIMIT ${LIMIT}
|
|
322
|
+
`;
|
|
323
|
+
/**
|
|
324
|
+
* Constraint names attached to a referenced table within a specific
|
|
325
|
+
* schema. Used when the user qualified the reference, e.g.
|
|
326
|
+
* `ALTER TABLE public."tab1" DROP CONSTRAINT t<TAB>`. The schema name is
|
|
327
|
+
* matched case-insensitively against `pg_namespace.nspname` so
|
|
328
|
+
* `PUBLIC.tab1` still resolves to constraints in the `public` schema.
|
|
329
|
+
*
|
|
330
|
+
* Caller passes `[schema, refName]` (with `refName` already case-folded
|
|
331
|
+
* for the unquoted form), and the ILIKE prefix as the trailing parameter.
|
|
332
|
+
*/
|
|
333
|
+
export const Query_for_constraint_of_table_in_schema = `
|
|
334
|
+
SELECT pg_catalog.quote_ident(con.conname)
|
|
335
|
+
FROM pg_catalog.pg_constraint con
|
|
336
|
+
JOIN pg_catalog.pg_class c ON con.conrelid = c.oid
|
|
337
|
+
JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
|
|
338
|
+
WHERE pg_catalog.lower(n.nspname) = pg_catalog.lower($1)
|
|
339
|
+
AND c.relname = $2
|
|
340
|
+
AND con.conname ILIKE $3
|
|
341
|
+
ORDER BY 1
|
|
342
|
+
LIMIT ${LIMIT}
|
|
343
|
+
`;
|
|
344
|
+
/**
|
|
345
|
+
* Tables (regular + partitioned) that have a constraint with the given
|
|
346
|
+
* name. The reverse direction of `Query_for_constraint_of_table` — used by
|
|
347
|
+
* the `COMMENT ON CONSTRAINT <name> ON <prefix>` completion to resolve the
|
|
348
|
+
* relation that owns the named constraint.
|
|
349
|
+
*
|
|
350
|
+
* Caller passes `[constraintName]`, then the ILIKE prefix on the relname.
|
|
351
|
+
* Mirrors upstream's `Query_for_list_of_tables_for_constraint` SchemaQuery
|
|
352
|
+
* (tab-complete.in.c ~line 694), which uses
|
|
353
|
+
* `selcondition = "c.oid=con.conrelid and c.relkind IN ('r','p')"` and
|
|
354
|
+
* `refname = "con.conname"`. The `quote_ident()` wrapper ensures
|
|
355
|
+
* names that need quoting (mixed case, reserved words) come back in a
|
|
356
|
+
* paste-safe form.
|
|
357
|
+
*/
|
|
358
|
+
export const Query_for_list_of_tables_for_constraint = `
|
|
359
|
+
SELECT DISTINCT pg_catalog.quote_ident(c.relname)
|
|
360
|
+
FROM pg_catalog.pg_class c, pg_catalog.pg_constraint con
|
|
361
|
+
WHERE c.oid = con.conrelid
|
|
362
|
+
AND c.relkind IN ('r', 'p')
|
|
363
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
364
|
+
AND con.conname = $1
|
|
365
|
+
AND c.relname ILIKE $2
|
|
366
|
+
ORDER BY 1
|
|
367
|
+
LIMIT ${LIMIT}
|
|
368
|
+
`;
|
|
369
|
+
/**
|
|
370
|
+
* Same as `Query_for_list_of_tables_for_constraint` but scoped to a
|
|
371
|
+
* specific schema (so `COMMENT ON CONSTRAINT foo ON public.<TAB>` only
|
|
372
|
+
* shows relations in `public`).
|
|
373
|
+
*
|
|
374
|
+
* Caller passes `[constraintName, schema]`, then the ILIKE prefix. Schema
|
|
375
|
+
* is matched case-insensitively to handle `PUBLIC.<TAB>` → `public.*`.
|
|
376
|
+
*/
|
|
377
|
+
export const Query_for_list_of_tables_for_constraint_in_schema = `
|
|
378
|
+
SELECT DISTINCT pg_catalog.quote_ident(c.relname)
|
|
379
|
+
FROM pg_catalog.pg_class c
|
|
380
|
+
JOIN pg_catalog.pg_constraint con ON c.oid = con.conrelid
|
|
381
|
+
JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
|
|
382
|
+
WHERE c.relkind IN ('r', 'p')
|
|
383
|
+
AND pg_catalog.lower(n.nspname) = pg_catalog.lower($2)
|
|
384
|
+
AND con.conname = $1
|
|
385
|
+
AND c.relname ILIKE $3
|
|
386
|
+
ORDER BY 1
|
|
387
|
+
LIMIT ${LIMIT}
|
|
388
|
+
`;
|
|
389
|
+
/**
|
|
390
|
+
* Enum label values for the named enum type. Mirrors upstream's
|
|
391
|
+
* `Query_for_list_of_enum_values_quoted` / `…_unquoted` (tab-complete.in.c
|
|
392
|
+
* ~line 602-618), with a parameter-bound type name in place of upstream's
|
|
393
|
+
* `set_completion_reference()` macro state.
|
|
394
|
+
*
|
|
395
|
+
* The caller picks the variant based on whether the user is mid-string-
|
|
396
|
+
* literal (current word starts with `'`), and passes `[typeName]` along
|
|
397
|
+
* with the ILIKE prefix as the trailing parameter. The quoted variant
|
|
398
|
+
* uses `quote_literal` so candidates come back as `'BLACK'` rather than
|
|
399
|
+
* bare `BLACK`, and the case-sensitive `enumlabel LIKE` ensures upstream
|
|
400
|
+
* parity for tests like `RENAME VALUE 'B<TAB>` → `'BLACK'`.
|
|
401
|
+
*/
|
|
402
|
+
export const Query_for_list_of_enum_values_quoted = `
|
|
403
|
+
SELECT pg_catalog.quote_literal(e.enumlabel)
|
|
404
|
+
FROM pg_catalog.pg_enum e, pg_catalog.pg_type t
|
|
405
|
+
WHERE t.oid = e.enumtypid
|
|
406
|
+
AND t.typname = $1
|
|
407
|
+
AND pg_catalog.pg_type_is_visible(t.oid)
|
|
408
|
+
AND e.enumlabel LIKE $2
|
|
409
|
+
ORDER BY 1
|
|
410
|
+
LIMIT ${LIMIT}
|
|
411
|
+
`;
|
|
412
|
+
export const Query_for_list_of_enum_values_unquoted = `
|
|
413
|
+
SELECT e.enumlabel
|
|
414
|
+
FROM pg_catalog.pg_enum e, pg_catalog.pg_type t
|
|
415
|
+
WHERE t.oid = e.enumtypid
|
|
416
|
+
AND t.typname = $1
|
|
417
|
+
AND pg_catalog.pg_type_is_visible(t.oid)
|
|
418
|
+
AND e.enumlabel LIKE $2
|
|
419
|
+
ORDER BY 1
|
|
420
|
+
LIMIT ${LIMIT}
|
|
421
|
+
`;
|
|
422
|
+
/**
|
|
423
|
+
* Timezone names from `pg_timezone_names()`. Three variants mirror
|
|
424
|
+
* upstream's `COMPLETE_WITH_TIMEZONE_NAME()` macro (tab-complete.in.c
|
|
425
|
+
* ~line 1160-1173) — different result shapes for the three contexts:
|
|
426
|
+
*
|
|
427
|
+
* - `…_unquoted` emits the bare name `America/New_York`. Used when
|
|
428
|
+
* the cursor is already inside an opened single-
|
|
429
|
+
* quoted string (`SET timezone TO 'America/New_<TAB>`),
|
|
430
|
+
* so the editor inserts the rest of the name and the
|
|
431
|
+
* closing quote.
|
|
432
|
+
* - `…_quoted_out` emits the candidate wrapped in single quotes —
|
|
433
|
+
* `'America/New_York'`. Used when the user hasn't
|
|
434
|
+
* typed any quote yet (`SET timezone TO am<TAB>` →
|
|
435
|
+
* `'America/`).
|
|
436
|
+
* - `…_quoted_in` emits the quoted form AND matches the quoted form
|
|
437
|
+
* against the LIKE pattern. Used when the user's
|
|
438
|
+
* partial word itself starts with `'` (so we feed
|
|
439
|
+
* `'am%` to the LIKE), so the editor can complete
|
|
440
|
+
* from inside the literal.
|
|
441
|
+
*
|
|
442
|
+
* All three are case-insensitive on the name (lower(name) LIKE lower(pat))
|
|
443
|
+
* because IANA names like `America/New_York` mix case but should still
|
|
444
|
+
* match a lowercase prefix.
|
|
445
|
+
*/
|
|
446
|
+
export const Query_for_list_of_timezone_names_unquoted = `
|
|
447
|
+
SELECT name
|
|
448
|
+
FROM pg_catalog.pg_timezone_names()
|
|
449
|
+
WHERE pg_catalog.lower(name) LIKE pg_catalog.lower($1)
|
|
450
|
+
ORDER BY 1
|
|
451
|
+
LIMIT ${LIMIT}
|
|
452
|
+
`;
|
|
453
|
+
export const Query_for_list_of_timezone_names_quoted_out = `
|
|
454
|
+
SELECT pg_catalog.quote_literal(name) AS name
|
|
455
|
+
FROM pg_catalog.pg_timezone_names()
|
|
456
|
+
WHERE pg_catalog.lower(name) LIKE pg_catalog.lower($1)
|
|
457
|
+
ORDER BY 1
|
|
458
|
+
LIMIT ${LIMIT}
|
|
459
|
+
`;
|
|
460
|
+
export const Query_for_list_of_timezone_names_quoted_in = `
|
|
461
|
+
SELECT pg_catalog.quote_literal(name) AS name
|
|
462
|
+
FROM pg_catalog.pg_timezone_names()
|
|
463
|
+
WHERE pg_catalog.quote_literal(pg_catalog.lower(name)) LIKE pg_catalog.lower($1)
|
|
464
|
+
ORDER BY 1
|
|
465
|
+
LIMIT ${LIMIT}
|
|
466
|
+
`;
|
|
467
|
+
/**
|
|
468
|
+
* Run one of the templates above against a connection and return the
|
|
469
|
+
* single-column results as a string array. Empty array on any error so the
|
|
470
|
+
* completer degrades gracefully — a flaky catalog query shouldn't crash the
|
|
471
|
+
* REPL.
|
|
472
|
+
*
|
|
473
|
+
* `pattern` is the user's partial input; we append `%` automatically.
|
|
474
|
+
*/
|
|
475
|
+
export const runCatalogQuery = async (conn, sql, pattern, extraParams = []) => {
|
|
476
|
+
try {
|
|
477
|
+
const likePattern = pattern + '%';
|
|
478
|
+
const params = extraParams.length > 0 ? [...extraParams, likePattern] : [likePattern];
|
|
479
|
+
const rs = await conn.query(sql, params);
|
|
480
|
+
const out = [];
|
|
481
|
+
for (const row of rs.rows) {
|
|
482
|
+
const v = row[0];
|
|
483
|
+
if (typeof v === 'string')
|
|
484
|
+
out.push(v);
|
|
485
|
+
}
|
|
486
|
+
return out;
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
return [];
|
|
490
|
+
}
|
|
491
|
+
};
|