neonctl 2.27.1 → 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 +35 -3
- package/dist/analytics.js +52 -34
- package/dist/api.js +643 -13
- package/dist/auth.js +50 -44
- package/dist/cli.js +8 -1
- package/dist/commands/auth.js +64 -51
- package/dist/commands/bootstrap.js +115 -157
- package/dist/commands/branches.js +160 -150
- package/dist/commands/bucket.js +183 -146
- package/dist/commands/checkout.js +51 -51
- package/dist/commands/config.js +228 -82
- package/dist/commands/connection_string.js +62 -62
- package/dist/commands/data_api.js +100 -101
- package/dist/commands/databases.js +29 -26
- 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 +101 -104
- package/dist/commands/index.js +27 -25
- package/dist/commands/init.js +23 -22
- package/dist/commands/ip_allow.js +29 -29
- package/dist/commands/link.js +232 -182
- package/dist/commands/neon_auth.js +385 -370
- package/dist/commands/operations.js +11 -11
- package/dist/commands/orgs.js +8 -8
- package/dist/commands/projects.js +103 -101
- package/dist/commands/psql.js +31 -31
- package/dist/commands/roles.js +27 -24
- package/dist/commands/schema_diff.js +25 -26
- package/dist/commands/set_context.js +17 -17
- package/dist/commands/status.js +40 -0
- 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 +37 -14
- package/dist/current_branch_fast_path.js +55 -0
- 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 +68 -5
- package/dist/functions_api.js +10 -10
- package/dist/help.js +15 -15
- package/dist/index.js +110 -107
- package/dist/log.js +2 -2
- package/dist/parameters.gen.js +14 -14
- 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 +22 -23
- package/dist/test_utils/fixtures.js +74 -41
- package/dist/test_utils/oauth_server.js +5 -5
- package/dist/utils/api_enums.js +33 -0
- 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 +28 -16
- 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 +10 -12
|
@@ -96,653 +96,653 @@
|
|
|
96
96
|
* The shape mirrors the C source closely enough that adding new rules is
|
|
97
97
|
* mechanical: drop a new `if (TailMatches(...))` arm in the right region.
|
|
98
98
|
*/
|
|
99
|
-
import { completeFilenames, isCopyFromOrTo } from
|
|
100
|
-
import { HeadMatches, MatchAny, TailMatches, tokenize } from
|
|
101
|
-
import {
|
|
102
|
-
import {
|
|
99
|
+
import { completeFilenames, isCopyFromOrTo } from "./filenames.js";
|
|
100
|
+
import { HeadMatches, MatchAny, TailMatches, tokenize } from "./matcher.js";
|
|
101
|
+
import { ENCODINGS, PSET_OPTIONS, psetValuesFor, SPECIAL_VARIABLES, variableValuesFor, } from "./psqlVars.js";
|
|
102
|
+
import { Query_for_constraint_of_table, Query_for_constraint_of_table_in_schema, Query_for_list_of_casts, Query_for_list_of_databases, Query_for_list_of_datatypes, Query_for_list_of_enum_values_quoted, Query_for_list_of_extensions, Query_for_list_of_functions, Query_for_list_of_index_access_methods, Query_for_list_of_indexes, Query_for_list_of_languages, Query_for_list_of_matviews, Query_for_list_of_operators, Query_for_list_of_publications, Query_for_list_of_relations_in_schema, Query_for_list_of_roles, Query_for_list_of_schemas, Query_for_list_of_sequences, Query_for_list_of_set_vars, Query_for_list_of_subscriptions, Query_for_list_of_tables, Query_for_list_of_tables_for_constraint, Query_for_list_of_tables_for_constraint_in_schema, Query_for_list_of_tables_views, Query_for_list_of_tablespaces, Query_for_list_of_timezone_names_quoted_in, Query_for_list_of_timezone_names_quoted_out, Query_for_list_of_types, Query_for_list_of_views, Query_for_values_of_enum_GUC, runCatalogQuery, } from "./queries.js";
|
|
103
103
|
/** Backslash command names psql tab-completes (mirrors backslash_commands[]). */
|
|
104
104
|
export const BACKSLASH_COMMANDS = [
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
105
|
+
"\\a",
|
|
106
|
+
"\\bind",
|
|
107
|
+
"\\bind_named",
|
|
108
|
+
"\\c",
|
|
109
|
+
"\\C",
|
|
110
|
+
"\\cd",
|
|
111
|
+
"\\close_prepared",
|
|
112
|
+
"\\conninfo",
|
|
113
|
+
"\\connect",
|
|
114
|
+
"\\copy",
|
|
115
|
+
"\\copyright",
|
|
116
|
+
"\\crosstabview",
|
|
117
|
+
"\\d",
|
|
118
|
+
"\\dA",
|
|
119
|
+
"\\dAc",
|
|
120
|
+
"\\dAf",
|
|
121
|
+
"\\dAo",
|
|
122
|
+
"\\dAp",
|
|
123
|
+
"\\da",
|
|
124
|
+
"\\db",
|
|
125
|
+
"\\dC",
|
|
126
|
+
"\\dc",
|
|
127
|
+
"\\dconfig",
|
|
128
|
+
"\\dD",
|
|
129
|
+
"\\dd",
|
|
130
|
+
"\\ddp",
|
|
131
|
+
"\\dE",
|
|
132
|
+
"\\des",
|
|
133
|
+
"\\det",
|
|
134
|
+
"\\deu",
|
|
135
|
+
"\\dew",
|
|
136
|
+
"\\df",
|
|
137
|
+
"\\dF",
|
|
138
|
+
"\\dFd",
|
|
139
|
+
"\\dFp",
|
|
140
|
+
"\\dFt",
|
|
141
|
+
"\\dg",
|
|
142
|
+
"\\di",
|
|
143
|
+
"\\dl",
|
|
144
|
+
"\\dL",
|
|
145
|
+
"\\dm",
|
|
146
|
+
"\\dn",
|
|
147
|
+
"\\do",
|
|
148
|
+
"\\dO",
|
|
149
|
+
"\\dp",
|
|
150
|
+
"\\dP",
|
|
151
|
+
"\\dPi",
|
|
152
|
+
"\\dPt",
|
|
153
|
+
"\\drds",
|
|
154
|
+
"\\drg",
|
|
155
|
+
"\\dRs",
|
|
156
|
+
"\\dRp",
|
|
157
|
+
"\\ds",
|
|
158
|
+
"\\dt",
|
|
159
|
+
"\\dT",
|
|
160
|
+
"\\dv",
|
|
161
|
+
"\\du",
|
|
162
|
+
"\\dx",
|
|
163
|
+
"\\dX",
|
|
164
|
+
"\\dy",
|
|
165
|
+
"\\echo",
|
|
166
|
+
"\\edit",
|
|
167
|
+
"\\ef",
|
|
168
|
+
"\\elif",
|
|
169
|
+
"\\else",
|
|
170
|
+
"\\encoding",
|
|
171
|
+
"\\endif",
|
|
172
|
+
"\\endpipeline",
|
|
173
|
+
"\\errverbose",
|
|
174
|
+
"\\ev",
|
|
175
|
+
"\\f",
|
|
176
|
+
"\\flush",
|
|
177
|
+
"\\flushrequest",
|
|
178
|
+
"\\g",
|
|
179
|
+
"\\gdesc",
|
|
180
|
+
"\\getenv",
|
|
181
|
+
"\\getresults",
|
|
182
|
+
"\\gexec",
|
|
183
|
+
"\\gset",
|
|
184
|
+
"\\gx",
|
|
185
|
+
"\\help",
|
|
186
|
+
"\\html",
|
|
187
|
+
"\\if",
|
|
188
|
+
"\\include",
|
|
189
|
+
"\\include_relative",
|
|
190
|
+
"\\ir",
|
|
191
|
+
"\\l",
|
|
192
|
+
"\\list",
|
|
193
|
+
"\\lo_export",
|
|
194
|
+
"\\lo_import",
|
|
195
|
+
"\\lo_list",
|
|
196
|
+
"\\lo_unlink",
|
|
197
|
+
"\\o",
|
|
198
|
+
"\\out",
|
|
199
|
+
"\\parse",
|
|
200
|
+
"\\password",
|
|
201
|
+
"\\print",
|
|
202
|
+
"\\prompt",
|
|
203
|
+
"\\pset",
|
|
204
|
+
"\\q",
|
|
205
|
+
"\\qecho",
|
|
206
|
+
"\\quit",
|
|
207
|
+
"\\reset",
|
|
208
|
+
"\\restrict",
|
|
209
|
+
"\\s",
|
|
210
|
+
"\\sendpipeline",
|
|
211
|
+
"\\set",
|
|
212
|
+
"\\setenv",
|
|
213
|
+
"\\sf",
|
|
214
|
+
"\\startpipeline",
|
|
215
|
+
"\\sv",
|
|
216
|
+
"\\syncpipeline",
|
|
217
|
+
"\\t",
|
|
218
|
+
"\\T",
|
|
219
|
+
"\\timing",
|
|
220
|
+
"\\unrestrict",
|
|
221
|
+
"\\unset",
|
|
222
|
+
"\\w",
|
|
223
|
+
"\\warn",
|
|
224
|
+
"\\watch",
|
|
225
|
+
"\\write",
|
|
226
|
+
"\\x",
|
|
227
|
+
"\\z",
|
|
228
|
+
"\\!",
|
|
229
|
+
"\\?",
|
|
230
230
|
];
|
|
231
231
|
/** Top-level SQL statement keywords. */
|
|
232
232
|
export const SQL_TOP_KEYWORDS = [
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
233
|
+
"ABORT",
|
|
234
|
+
"ALTER",
|
|
235
|
+
"ANALYZE",
|
|
236
|
+
"BEGIN",
|
|
237
|
+
"CALL",
|
|
238
|
+
"CHECKPOINT",
|
|
239
|
+
"CLOSE",
|
|
240
|
+
"CLUSTER",
|
|
241
|
+
"COMMENT",
|
|
242
|
+
"COMMIT",
|
|
243
|
+
"COPY",
|
|
244
|
+
"CREATE",
|
|
245
|
+
"DEALLOCATE",
|
|
246
|
+
"DECLARE",
|
|
247
|
+
"DELETE FROM",
|
|
248
|
+
"DISCARD",
|
|
249
|
+
"DO",
|
|
250
|
+
"DROP",
|
|
251
|
+
"END",
|
|
252
|
+
"EXECUTE",
|
|
253
|
+
"EXPLAIN",
|
|
254
|
+
"FETCH",
|
|
255
|
+
"GRANT",
|
|
256
|
+
"IMPORT",
|
|
257
|
+
"INSERT INTO",
|
|
258
|
+
"LISTEN",
|
|
259
|
+
"LOAD",
|
|
260
|
+
"LOCK",
|
|
261
|
+
"MERGE",
|
|
262
|
+
"MOVE",
|
|
263
|
+
"NOTIFY",
|
|
264
|
+
"PREPARE",
|
|
265
|
+
"REASSIGN",
|
|
266
|
+
"REFRESH MATERIALIZED VIEW",
|
|
267
|
+
"REINDEX",
|
|
268
|
+
"RELEASE",
|
|
269
|
+
"RESET",
|
|
270
|
+
"REVOKE",
|
|
271
|
+
"ROLLBACK",
|
|
272
|
+
"SAVEPOINT",
|
|
273
|
+
"SECURITY LABEL",
|
|
274
|
+
"SELECT",
|
|
275
|
+
"SET",
|
|
276
|
+
"SHOW",
|
|
277
|
+
"START TRANSACTION",
|
|
278
|
+
"TABLE",
|
|
279
|
+
"TRUNCATE",
|
|
280
|
+
"UNLISTEN",
|
|
281
|
+
"UPDATE",
|
|
282
|
+
"VACUUM",
|
|
283
|
+
"VALUES",
|
|
284
|
+
"WITH",
|
|
285
285
|
];
|
|
286
286
|
/** Keywords accepted after CREATE. */
|
|
287
287
|
export const CREATE_OBJECTS = [
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
288
|
+
"ACCESS METHOD",
|
|
289
|
+
"AGGREGATE",
|
|
290
|
+
"CAST",
|
|
291
|
+
"COLLATION",
|
|
292
|
+
"CONVERSION",
|
|
293
|
+
"DATABASE",
|
|
294
|
+
"DEFAULT PRIVILEGES",
|
|
295
|
+
"DOMAIN",
|
|
296
|
+
"EVENT TRIGGER",
|
|
297
|
+
"EXTENSION",
|
|
298
|
+
"FOREIGN DATA WRAPPER",
|
|
299
|
+
"FOREIGN TABLE",
|
|
300
|
+
"FUNCTION",
|
|
301
|
+
"GLOBAL",
|
|
302
|
+
"GROUP",
|
|
303
|
+
"INDEX",
|
|
304
|
+
"LANGUAGE",
|
|
305
|
+
"LOCAL",
|
|
306
|
+
"MATERIALIZED VIEW",
|
|
307
|
+
"OPERATOR",
|
|
308
|
+
"OR REPLACE",
|
|
309
|
+
"POLICY",
|
|
310
|
+
"PROCEDURE",
|
|
311
|
+
"PUBLICATION",
|
|
312
|
+
"ROLE",
|
|
313
|
+
"RULE",
|
|
314
|
+
"SCHEMA",
|
|
315
|
+
"SEQUENCE",
|
|
316
|
+
"SERVER",
|
|
317
|
+
"STATISTICS",
|
|
318
|
+
"SUBSCRIPTION",
|
|
319
|
+
"TABLE",
|
|
320
|
+
"TABLESPACE",
|
|
321
|
+
"TEMP",
|
|
322
|
+
"TEMPORARY",
|
|
323
|
+
"TEXT SEARCH",
|
|
324
|
+
"TRANSFORM",
|
|
325
|
+
"TRIGGER",
|
|
326
|
+
"TYPE",
|
|
327
|
+
"UNIQUE",
|
|
328
|
+
"UNLOGGED",
|
|
329
|
+
"USER",
|
|
330
|
+
"VIEW",
|
|
331
331
|
];
|
|
332
332
|
/** Keywords accepted after DROP. */
|
|
333
333
|
export const DROP_OBJECTS = [
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
334
|
+
"ACCESS METHOD",
|
|
335
|
+
"AGGREGATE",
|
|
336
|
+
"CAST",
|
|
337
|
+
"COLLATION",
|
|
338
|
+
"CONVERSION",
|
|
339
|
+
"DATABASE",
|
|
340
|
+
"DOMAIN",
|
|
341
|
+
"EVENT TRIGGER",
|
|
342
|
+
"EXTENSION",
|
|
343
|
+
"FOREIGN DATA WRAPPER",
|
|
344
|
+
"FOREIGN TABLE",
|
|
345
|
+
"FUNCTION",
|
|
346
|
+
"GROUP",
|
|
347
|
+
"INDEX",
|
|
348
|
+
"LANGUAGE",
|
|
349
|
+
"MATERIALIZED VIEW",
|
|
350
|
+
"OPERATOR",
|
|
351
|
+
"OWNED",
|
|
352
|
+
"POLICY",
|
|
353
|
+
"PROCEDURE",
|
|
354
|
+
"PUBLICATION",
|
|
355
|
+
"ROLE",
|
|
356
|
+
"RULE",
|
|
357
|
+
"SCHEMA",
|
|
358
|
+
"SEQUENCE",
|
|
359
|
+
"SERVER",
|
|
360
|
+
"STATISTICS",
|
|
361
|
+
"SUBSCRIPTION",
|
|
362
|
+
"TABLE",
|
|
363
|
+
"TABLESPACE",
|
|
364
|
+
"TEXT SEARCH",
|
|
365
|
+
"TRANSFORM",
|
|
366
|
+
"TRIGGER",
|
|
367
|
+
"TYPE",
|
|
368
|
+
"USER",
|
|
369
|
+
"VIEW",
|
|
370
370
|
];
|
|
371
371
|
/** Keywords accepted after ALTER. */
|
|
372
372
|
export const ALTER_OBJECTS = [
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
373
|
+
"AGGREGATE",
|
|
374
|
+
"COLLATION",
|
|
375
|
+
"CONVERSION",
|
|
376
|
+
"DATABASE",
|
|
377
|
+
"DEFAULT PRIVILEGES",
|
|
378
|
+
"DOMAIN",
|
|
379
|
+
"EVENT TRIGGER",
|
|
380
|
+
"EXTENSION",
|
|
381
|
+
"FOREIGN DATA WRAPPER",
|
|
382
|
+
"FOREIGN TABLE",
|
|
383
|
+
"FUNCTION",
|
|
384
|
+
"GROUP",
|
|
385
|
+
"INDEX",
|
|
386
|
+
"LANGUAGE",
|
|
387
|
+
"LARGE OBJECT",
|
|
388
|
+
"MATERIALIZED VIEW",
|
|
389
|
+
"OPERATOR",
|
|
390
|
+
"POLICY",
|
|
391
|
+
"PROCEDURE",
|
|
392
|
+
"PUBLICATION",
|
|
393
|
+
"ROLE",
|
|
394
|
+
"RULE",
|
|
395
|
+
"SCHEMA",
|
|
396
|
+
"SEQUENCE",
|
|
397
|
+
"SERVER",
|
|
398
|
+
"STATISTICS",
|
|
399
|
+
"SUBSCRIPTION",
|
|
400
|
+
"SYSTEM",
|
|
401
|
+
"TABLE",
|
|
402
|
+
"TABLESPACE",
|
|
403
|
+
"TEXT SEARCH",
|
|
404
|
+
"TRIGGER",
|
|
405
|
+
"TYPE",
|
|
406
|
+
"USER",
|
|
407
|
+
"VIEW",
|
|
408
408
|
];
|
|
409
409
|
/** Sub-actions for ALTER TABLE. */
|
|
410
410
|
export const ALTER_TABLE_ACTIONS = [
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
411
|
+
"ADD",
|
|
412
|
+
"ALTER",
|
|
413
|
+
"ATTACH PARTITION",
|
|
414
|
+
"CLUSTER ON",
|
|
415
|
+
"DETACH PARTITION",
|
|
416
|
+
"DISABLE",
|
|
417
|
+
"DROP",
|
|
418
|
+
"ENABLE",
|
|
419
|
+
"INHERIT",
|
|
420
|
+
"NO INHERIT",
|
|
421
|
+
"OF",
|
|
422
|
+
"NOT OF",
|
|
423
|
+
"OWNER TO",
|
|
424
|
+
"RENAME",
|
|
425
|
+
"REPLICA IDENTITY",
|
|
426
|
+
"RESET",
|
|
427
|
+
"SET",
|
|
428
|
+
"VALIDATE CONSTRAINT",
|
|
429
429
|
];
|
|
430
430
|
/** Continuation after `ALTER TABLE x ADD`. */
|
|
431
431
|
export const ALTER_TABLE_ADD = [
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
432
|
+
"COLUMN",
|
|
433
|
+
"CONSTRAINT",
|
|
434
|
+
"CHECK",
|
|
435
|
+
"FOREIGN KEY",
|
|
436
|
+
"PRIMARY KEY",
|
|
437
|
+
"UNIQUE",
|
|
438
|
+
"EXCLUDE",
|
|
439
439
|
];
|
|
440
440
|
/** Continuation after `ALTER TABLE x ALTER [COLUMN] y`. */
|
|
441
441
|
export const ALTER_TABLE_ALTER_COLUMN = [
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
442
|
+
"ADD GENERATED",
|
|
443
|
+
"DROP DEFAULT",
|
|
444
|
+
"DROP EXPRESSION",
|
|
445
|
+
"DROP IDENTITY",
|
|
446
|
+
"DROP NOT NULL",
|
|
447
|
+
"RESET",
|
|
448
|
+
"RESTART",
|
|
449
|
+
"SET",
|
|
450
|
+
"SET DATA TYPE",
|
|
451
|
+
"SET DEFAULT",
|
|
452
|
+
"SET EXPRESSION",
|
|
453
|
+
"SET GENERATED",
|
|
454
|
+
"SET NOT NULL",
|
|
455
|
+
"SET STATISTICS",
|
|
456
|
+
"SET STORAGE",
|
|
457
|
+
"TYPE",
|
|
458
458
|
];
|
|
459
459
|
/** Continuation after `ALTER TABLE x DROP`. */
|
|
460
460
|
export const ALTER_TABLE_DROP = [
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
461
|
+
"COLUMN",
|
|
462
|
+
"CONSTRAINT",
|
|
463
|
+
"IF EXISTS",
|
|
464
464
|
];
|
|
465
465
|
/** Continuation after `ALTER TABLE x RENAME`. */
|
|
466
466
|
export const ALTER_TABLE_RENAME = [
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
467
|
+
"COLUMN",
|
|
468
|
+
"CONSTRAINT",
|
|
469
|
+
"TO",
|
|
470
470
|
];
|
|
471
471
|
/** Continuation after `ALTER TABLE x SET`. */
|
|
472
472
|
export const ALTER_TABLE_SET = [
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
473
|
+
"(",
|
|
474
|
+
"LOGGED",
|
|
475
|
+
"SCHEMA",
|
|
476
|
+
"TABLESPACE",
|
|
477
|
+
"UNLOGGED",
|
|
478
|
+
"WITHOUT CLUSTER",
|
|
479
|
+
"WITHOUT OIDS",
|
|
480
480
|
];
|
|
481
481
|
/** Continuation after `ALTER TABLE x ENABLE`. */
|
|
482
482
|
export const ALTER_TABLE_ENABLE = [
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
483
|
+
"ALWAYS",
|
|
484
|
+
"REPLICA",
|
|
485
|
+
"ROW LEVEL SECURITY",
|
|
486
|
+
"RULE",
|
|
487
|
+
"TRIGGER",
|
|
488
488
|
];
|
|
489
489
|
/** Continuation after `ALTER TABLE x DISABLE`. */
|
|
490
490
|
export const ALTER_TABLE_DISABLE = [
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
491
|
+
"ROW LEVEL SECURITY",
|
|
492
|
+
"RULE",
|
|
493
|
+
"TRIGGER",
|
|
494
494
|
];
|
|
495
495
|
/** Continuation after `ALTER TABLE x REPLICA IDENTITY`. */
|
|
496
496
|
export const ALTER_TABLE_REPLICA_IDENTITY = [
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
497
|
+
"DEFAULT",
|
|
498
|
+
"FULL",
|
|
499
|
+
"NOTHING",
|
|
500
|
+
"USING INDEX",
|
|
501
501
|
];
|
|
502
502
|
/** Sub-actions for ALTER VIEW. */
|
|
503
503
|
export const ALTER_VIEW_ACTIONS = [
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
504
|
+
"ALTER",
|
|
505
|
+
"OWNER TO",
|
|
506
|
+
"RENAME",
|
|
507
|
+
"RESET",
|
|
508
|
+
"SET",
|
|
509
509
|
];
|
|
510
510
|
/** Sub-actions for ALTER MATERIALIZED VIEW. */
|
|
511
511
|
export const ALTER_MATVIEW_ACTIONS = [
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
512
|
+
"ALTER",
|
|
513
|
+
"CLUSTER ON",
|
|
514
|
+
"DEPENDS ON EXTENSION",
|
|
515
|
+
"NO DEPENDS ON EXTENSION",
|
|
516
|
+
"OWNER TO",
|
|
517
|
+
"RENAME",
|
|
518
|
+
"RESET",
|
|
519
|
+
"SET",
|
|
520
520
|
];
|
|
521
521
|
/** Sub-actions for ALTER INDEX. */
|
|
522
522
|
export const ALTER_INDEX_ACTIONS = [
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
523
|
+
"ALTER COLUMN",
|
|
524
|
+
"ATTACH PARTITION",
|
|
525
|
+
"DEPENDS ON EXTENSION",
|
|
526
|
+
"NO DEPENDS ON EXTENSION",
|
|
527
|
+
"OWNER TO",
|
|
528
|
+
"RENAME",
|
|
529
|
+
"RESET",
|
|
530
|
+
"SET",
|
|
531
531
|
];
|
|
532
532
|
/** Sub-actions for ALTER SEQUENCE. */
|
|
533
533
|
export const ALTER_SEQUENCE_ACTIONS = [
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
534
|
+
"AS",
|
|
535
|
+
"CACHE",
|
|
536
|
+
"CYCLE",
|
|
537
|
+
"INCREMENT BY",
|
|
538
|
+
"MAXVALUE",
|
|
539
|
+
"MINVALUE",
|
|
540
|
+
"NO CYCLE",
|
|
541
|
+
"NO MAXVALUE",
|
|
542
|
+
"NO MINVALUE",
|
|
543
|
+
"OWNED BY",
|
|
544
|
+
"OWNER TO",
|
|
545
|
+
"RENAME TO",
|
|
546
|
+
"RESTART",
|
|
547
|
+
"SET SCHEMA",
|
|
548
|
+
"START WITH",
|
|
549
549
|
];
|
|
550
550
|
/** Sub-actions for ALTER FUNCTION / PROCEDURE / ROUTINE. */
|
|
551
551
|
export const ALTER_FUNCTION_ACTIONS = [
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
552
|
+
"CALLED ON NULL INPUT",
|
|
553
|
+
"COST",
|
|
554
|
+
"DEPENDS ON EXTENSION",
|
|
555
|
+
"IMMUTABLE",
|
|
556
|
+
"LEAKPROOF",
|
|
557
|
+
"NO DEPENDS ON EXTENSION",
|
|
558
|
+
"NOT LEAKPROOF",
|
|
559
|
+
"OWNER TO",
|
|
560
|
+
"PARALLEL",
|
|
561
|
+
"RENAME TO",
|
|
562
|
+
"RESET",
|
|
563
|
+
"RETURNS NULL ON NULL INPUT",
|
|
564
|
+
"ROWS",
|
|
565
|
+
"SECURITY DEFINER",
|
|
566
|
+
"SECURITY INVOKER",
|
|
567
|
+
"SET",
|
|
568
|
+
"SET SCHEMA",
|
|
569
|
+
"STABLE",
|
|
570
|
+
"STRICT",
|
|
571
|
+
"SUPPORT",
|
|
572
|
+
"VOLATILE",
|
|
573
573
|
];
|
|
574
574
|
/** Sub-actions for ALTER TYPE. */
|
|
575
575
|
export const ALTER_TYPE_ACTIONS = [
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
576
|
+
"ADD ATTRIBUTE",
|
|
577
|
+
"ADD VALUE",
|
|
578
|
+
"ALTER ATTRIBUTE",
|
|
579
|
+
"DROP ATTRIBUTE",
|
|
580
|
+
"OWNER TO",
|
|
581
|
+
"RENAME",
|
|
582
|
+
"RENAME ATTRIBUTE",
|
|
583
|
+
"RENAME VALUE",
|
|
584
|
+
"SET SCHEMA",
|
|
585
|
+
"SET",
|
|
586
586
|
];
|
|
587
587
|
/** Sub-actions for ALTER ROLE / USER. */
|
|
588
588
|
export const ALTER_ROLE_ACTIONS = [
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
589
|
+
"BYPASSRLS",
|
|
590
|
+
"CONNECTION LIMIT",
|
|
591
|
+
"CREATEDB",
|
|
592
|
+
"CREATEROLE",
|
|
593
|
+
"ENCRYPTED PASSWORD",
|
|
594
|
+
"IN DATABASE",
|
|
595
|
+
"INHERIT",
|
|
596
|
+
"LOGIN",
|
|
597
|
+
"NOBYPASSRLS",
|
|
598
|
+
"NOCREATEDB",
|
|
599
|
+
"NOCREATEROLE",
|
|
600
|
+
"NOINHERIT",
|
|
601
|
+
"NOLOGIN",
|
|
602
|
+
"NOREPLICATION",
|
|
603
|
+
"NOSUPERUSER",
|
|
604
|
+
"PASSWORD",
|
|
605
|
+
"RENAME TO",
|
|
606
|
+
"REPLICATION",
|
|
607
|
+
"RESET",
|
|
608
|
+
"SET",
|
|
609
|
+
"SUPERUSER",
|
|
610
|
+
"VALID UNTIL",
|
|
611
|
+
"WITH",
|
|
612
612
|
];
|
|
613
613
|
/** Sub-actions for ALTER DATABASE. */
|
|
614
614
|
export const ALTER_DATABASE_ACTIONS = [
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
615
|
+
"ALLOW_CONNECTIONS",
|
|
616
|
+
"CONNECTION LIMIT",
|
|
617
|
+
"IS_TEMPLATE",
|
|
618
|
+
"OWNER TO",
|
|
619
|
+
"REFRESH COLLATION VERSION",
|
|
620
|
+
"RENAME TO",
|
|
621
|
+
"RESET",
|
|
622
|
+
"SET",
|
|
623
|
+
"SET TABLESPACE",
|
|
624
|
+
"WITH",
|
|
625
625
|
];
|
|
626
626
|
/** Sub-actions for ALTER SCHEMA. */
|
|
627
627
|
export const ALTER_SCHEMA_ACTIONS = [
|
|
628
|
-
|
|
629
|
-
|
|
628
|
+
"OWNER TO",
|
|
629
|
+
"RENAME TO",
|
|
630
630
|
];
|
|
631
631
|
/** Sub-actions for ALTER EXTENSION. */
|
|
632
632
|
export const ALTER_EXTENSION_ACTIONS = [
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
633
|
+
"ADD",
|
|
634
|
+
"DROP",
|
|
635
|
+
"SET SCHEMA",
|
|
636
|
+
"UPDATE",
|
|
637
637
|
];
|
|
638
638
|
/** Sub-actions for ALTER POLICY. */
|
|
639
|
-
export const ALTER_POLICY_ACTIONS = [
|
|
639
|
+
export const ALTER_POLICY_ACTIONS = ["ON", "RENAME TO"];
|
|
640
640
|
/** Sub-actions for ALTER PUBLICATION. */
|
|
641
641
|
export const ALTER_PUBLICATION_ACTIONS = [
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
642
|
+
"ADD",
|
|
643
|
+
"DROP",
|
|
644
|
+
"OWNER TO",
|
|
645
|
+
"RENAME TO",
|
|
646
|
+
"SET",
|
|
647
647
|
];
|
|
648
648
|
/** Sub-actions for ALTER SUBSCRIPTION. */
|
|
649
649
|
export const ALTER_SUBSCRIPTION_ACTIONS = [
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
650
|
+
"ADD PUBLICATION",
|
|
651
|
+
"CONNECTION",
|
|
652
|
+
"DISABLE",
|
|
653
|
+
"DROP PUBLICATION",
|
|
654
|
+
"ENABLE",
|
|
655
|
+
"OWNER TO",
|
|
656
|
+
"REFRESH PUBLICATION",
|
|
657
|
+
"RENAME TO",
|
|
658
|
+
"SET",
|
|
659
|
+
"SET PUBLICATION",
|
|
660
|
+
"SKIP",
|
|
661
661
|
];
|
|
662
662
|
/** CREATE INDEX top-level options. */
|
|
663
663
|
export const CREATE_INDEX_OPTIONS = [
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
664
|
+
"CONCURRENTLY",
|
|
665
|
+
"IF NOT EXISTS",
|
|
666
|
+
"ON",
|
|
667
|
+
"UNIQUE",
|
|
668
668
|
];
|
|
669
669
|
/** Window frame clauses after `OVER (`. */
|
|
670
670
|
export const WINDOW_FRAME_KEYWORDS = [
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
671
|
+
"GROUPS",
|
|
672
|
+
"ORDER BY",
|
|
673
|
+
"PARTITION BY",
|
|
674
|
+
"RANGE",
|
|
675
|
+
"ROWS",
|
|
676
676
|
];
|
|
677
677
|
/** Tail keywords that follow a `FROM <table>` clause in a query. */
|
|
678
678
|
export const POST_FROM_KEYWORDS = [
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
679
|
+
"AS",
|
|
680
|
+
"CROSS JOIN",
|
|
681
|
+
"EXCEPT",
|
|
682
|
+
"FETCH",
|
|
683
|
+
"FOR",
|
|
684
|
+
"FULL JOIN",
|
|
685
|
+
"FULL OUTER JOIN",
|
|
686
|
+
"GROUP BY",
|
|
687
|
+
"HAVING",
|
|
688
|
+
"INNER JOIN",
|
|
689
|
+
"INTERSECT",
|
|
690
|
+
"JOIN",
|
|
691
|
+
"LATERAL",
|
|
692
|
+
"LEFT JOIN",
|
|
693
|
+
"LEFT OUTER JOIN",
|
|
694
|
+
"LIMIT",
|
|
695
|
+
"NATURAL JOIN",
|
|
696
|
+
"OFFSET",
|
|
697
|
+
"ON",
|
|
698
|
+
"ORDER BY",
|
|
699
|
+
"RIGHT JOIN",
|
|
700
|
+
"RIGHT OUTER JOIN",
|
|
701
|
+
"TABLESAMPLE",
|
|
702
|
+
"UNION",
|
|
703
|
+
"USING",
|
|
704
|
+
"WHERE",
|
|
705
|
+
"WINDOW",
|
|
706
706
|
];
|
|
707
707
|
/** Continuations within a WHERE expression. */
|
|
708
708
|
export const WHERE_CONTINUATIONS = [
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
709
|
+
"AND",
|
|
710
|
+
"BETWEEN",
|
|
711
|
+
"IN",
|
|
712
|
+
"IS",
|
|
713
|
+
"LIKE",
|
|
714
|
+
"NOT",
|
|
715
|
+
"OR",
|
|
716
716
|
];
|
|
717
717
|
/** Boolean-style values used with `\set` for AUTOCOMMIT etc. (extends ON_OFF). */
|
|
718
718
|
export const DATESTYLE_VALUES = [
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
719
|
+
"GERMAN",
|
|
720
|
+
"ISO",
|
|
721
|
+
"POSTGRES",
|
|
722
|
+
"SQL",
|
|
723
723
|
];
|
|
724
724
|
/** GRANT / REVOKE privileges. */
|
|
725
725
|
export const PRIVILEGE_KEYWORDS = [
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
726
|
+
"ALL",
|
|
727
|
+
"CREATE",
|
|
728
|
+
"CONNECT",
|
|
729
|
+
"DELETE",
|
|
730
|
+
"EXECUTE",
|
|
731
|
+
"INSERT",
|
|
732
|
+
"REFERENCES",
|
|
733
|
+
"SELECT",
|
|
734
|
+
"TEMPORARY",
|
|
735
|
+
"TRIGGER",
|
|
736
|
+
"TRUNCATE",
|
|
737
|
+
"UPDATE",
|
|
738
|
+
"USAGE",
|
|
739
739
|
];
|
|
740
740
|
/** Common transaction/savepoint keywords. */
|
|
741
741
|
export const TRANSACTION_KEYWORDS = [
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
742
|
+
"ISOLATION LEVEL",
|
|
743
|
+
"READ ONLY",
|
|
744
|
+
"READ WRITE",
|
|
745
|
+
"TRANSACTION",
|
|
746
746
|
];
|
|
747
747
|
/**
|
|
748
748
|
* Built-in scalar type keywords that psql tab-completion mixes in
|
|
@@ -753,13 +753,13 @@ export const TRANSACTION_KEYWORDS = [
|
|
|
753
753
|
* boundaries.
|
|
754
754
|
*/
|
|
755
755
|
export const BUILTIN_DATATYPE_KEYWORDS = [
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
756
|
+
"bigint",
|
|
757
|
+
"boolean",
|
|
758
|
+
"character",
|
|
759
|
+
"double precision",
|
|
760
|
+
"integer",
|
|
761
|
+
"real",
|
|
762
|
+
"smallint",
|
|
763
763
|
];
|
|
764
764
|
/**
|
|
765
765
|
* COPY ... FROM ... WITH ( ... ) option keywords. Mirrors upstream's
|
|
@@ -768,34 +768,34 @@ export const BUILTIN_DATATYPE_KEYWORDS = [
|
|
|
768
768
|
* ON_ERROR, REJECT_LIMIT).
|
|
769
769
|
*/
|
|
770
770
|
export const COPY_FROM_OPTIONS = [
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
771
|
+
"DELIMITER",
|
|
772
|
+
"ENCODING",
|
|
773
|
+
"ESCAPE",
|
|
774
|
+
"FORMAT",
|
|
775
|
+
"HEADER",
|
|
776
|
+
"NULL",
|
|
777
|
+
"QUOTE",
|
|
778
|
+
"DEFAULT",
|
|
779
|
+
"FORCE_NOT_NULL",
|
|
780
|
+
"FORCE_NULL",
|
|
781
|
+
"FREEZE",
|
|
782
|
+
"LOG_VERBOSITY",
|
|
783
|
+
"ON_ERROR",
|
|
784
|
+
"REJECT_LIMIT",
|
|
785
785
|
];
|
|
786
786
|
/**
|
|
787
787
|
* COPY ... TO ... WITH ( ... ) option keywords. Mirrors upstream's
|
|
788
788
|
* `Copy_to_options` macro = `Copy_common_options` + `FORCE_QUOTE`.
|
|
789
789
|
*/
|
|
790
790
|
export const COPY_TO_OPTIONS = [
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
791
|
+
"DELIMITER",
|
|
792
|
+
"ENCODING",
|
|
793
|
+
"ESCAPE",
|
|
794
|
+
"FORMAT",
|
|
795
|
+
"HEADER",
|
|
796
|
+
"NULL",
|
|
797
|
+
"QUOTE",
|
|
798
|
+
"FORCE_QUOTE",
|
|
799
799
|
];
|
|
800
800
|
/**
|
|
801
801
|
* Apply a case-insensitive prefix filter. Empty `prefix` returns the whole
|
|
@@ -848,14 +848,14 @@ const applyCase = (candidate, typed, settings) => {
|
|
|
848
848
|
// - preserve-lower → lowercase.
|
|
849
849
|
// The same rule applies when the first char is a non-letter (digit, `_`,
|
|
850
850
|
// punctuation) — those preserve the mode's default direction.
|
|
851
|
-
const first = typed[0] ??
|
|
851
|
+
const first = typed[0] ?? "";
|
|
852
852
|
const firstIsLower = /[a-z]/.test(first);
|
|
853
853
|
const firstIsAlpha = /[A-Za-z]/.test(first);
|
|
854
|
-
const lowerCaseIt = mode ===
|
|
855
|
-
((mode ===
|
|
854
|
+
const lowerCaseIt = mode === "lower" ||
|
|
855
|
+
((mode === "preserve-lower" || mode === "preserve-upper") &&
|
|
856
856
|
firstIsLower) ||
|
|
857
|
-
(mode ===
|
|
858
|
-
if (mode ===
|
|
857
|
+
(mode === "preserve-lower" && !firstIsAlpha);
|
|
858
|
+
if (mode === "upper")
|
|
859
859
|
return candidate.toUpperCase();
|
|
860
860
|
return lowerCaseIt ? candidate.toLowerCase() : candidate.toUpperCase();
|
|
861
861
|
};
|
|
@@ -867,13 +867,13 @@ const containsNonKeywordChar = (s) => /[^A-Za-z0-9 ]/.test(s);
|
|
|
867
867
|
* to fold its case in the rendered output.
|
|
868
868
|
*/
|
|
869
869
|
const splitSchemaPrefix = (word) => {
|
|
870
|
-
const dot = word.indexOf(
|
|
870
|
+
const dot = word.indexOf(".");
|
|
871
871
|
if (dot < 0)
|
|
872
872
|
return null;
|
|
873
873
|
// Reject if anything after the dot looks like another dot (we only handle
|
|
874
874
|
// schema.relation, not catalog.schema.relation).
|
|
875
875
|
const after = word.slice(dot + 1);
|
|
876
|
-
if (after.includes(
|
|
876
|
+
if (after.includes("."))
|
|
877
877
|
return null;
|
|
878
878
|
// Strip optional quoting on the schema.
|
|
879
879
|
let schema = word.slice(0, dot);
|
|
@@ -914,7 +914,7 @@ const parseTableRef = (refTokens) => {
|
|
|
914
914
|
// token on the dot when the relation half is quoted).
|
|
915
915
|
if (refTokens.length === 2) {
|
|
916
916
|
const first = refTokens[0];
|
|
917
|
-
if (!first.endsWith(
|
|
917
|
+
if (!first.endsWith("."))
|
|
918
918
|
return null;
|
|
919
919
|
const s = stripQuote(first.slice(0, -1));
|
|
920
920
|
const t = stripQuote(refTokens[1]);
|
|
@@ -937,7 +937,7 @@ const parseTableRef = (refTokens) => {
|
|
|
937
937
|
if (ch === '"') {
|
|
938
938
|
inQuote = !inQuote;
|
|
939
939
|
}
|
|
940
|
-
else if (ch ===
|
|
940
|
+
else if (ch === "." && !inQuote) {
|
|
941
941
|
dot = i;
|
|
942
942
|
break;
|
|
943
943
|
}
|
|
@@ -974,18 +974,18 @@ export const findCompletions = async (prevWords, currentWord, ctx) => {
|
|
|
974
974
|
// takes priority over anything else. The interpolation forms are valid
|
|
975
975
|
// both inside SQL and inside backslash-command args (`\echo :VERB`),
|
|
976
976
|
// so this branch fires regardless of `prevWords`.
|
|
977
|
-
if (currentWord.startsWith(
|
|
977
|
+
if (currentWord.startsWith(":") && !currentWord.startsWith("::")) {
|
|
978
978
|
const names = listVarNames(ctx.settings);
|
|
979
979
|
const lc = (s) => s.toLowerCase();
|
|
980
980
|
// `:{?NAME}` — test-form (psqlscan_test_variable upstream). The
|
|
981
981
|
// candidate must close the `}` so the user's literal `:{?VERB`
|
|
982
982
|
// expands to `:{?VERBOSITY}` in one Tab.
|
|
983
|
-
if (currentWord.startsWith(
|
|
983
|
+
if (currentWord.startsWith(":{?")) {
|
|
984
984
|
const prefix = currentWord.slice(3);
|
|
985
985
|
const lp = lc(prefix);
|
|
986
986
|
const cands = names
|
|
987
987
|
.filter((n) => lc(n).startsWith(lp))
|
|
988
|
-
.map((n) =>
|
|
988
|
+
.map((n) => ":{?" + n + "}");
|
|
989
989
|
return { candidates: cands };
|
|
990
990
|
}
|
|
991
991
|
// `:'NAME'` / `:"NAME"` — quoted-substitution forms (psqlscan emits
|
|
@@ -1010,18 +1010,20 @@ export const findCompletions = async (prevWords, currentWord, ctx) => {
|
|
|
1010
1010
|
// Plain `:NAME` — bare substitution.
|
|
1011
1011
|
const prefix = currentWord.slice(1);
|
|
1012
1012
|
const lp = lc(prefix);
|
|
1013
|
-
const filt = names
|
|
1013
|
+
const filt = names
|
|
1014
|
+
.filter((n) => lc(n).startsWith(lp))
|
|
1015
|
+
.map((n) => ":" + n);
|
|
1014
1016
|
return { candidates: filt };
|
|
1015
1017
|
}
|
|
1016
1018
|
// ----- Backslash-command name completion.
|
|
1017
1019
|
// Trigger: the user is mid-token and the token starts with '\'.
|
|
1018
|
-
if (currentWord.startsWith(
|
|
1020
|
+
if (currentWord.startsWith("\\") && prevWords.length === 0) {
|
|
1019
1021
|
return {
|
|
1020
1022
|
candidates: BACKSLASH_COMMANDS.filter((c) => c.toLowerCase().startsWith(currentWord.toLowerCase())),
|
|
1021
1023
|
};
|
|
1022
1024
|
}
|
|
1023
1025
|
// ----- Backslash-command argument completion.
|
|
1024
|
-
if (prevWords.length > 0 && prevWords[0].startsWith(
|
|
1026
|
+
if (prevWords.length > 0 && prevWords[0].startsWith("\\")) {
|
|
1025
1027
|
return await backslashArgRules(prevWords, currentWord, ctx, conn);
|
|
1026
1028
|
}
|
|
1027
1029
|
// ----- Multi-line SQL: rules that need to see across the line boundary
|
|
@@ -1096,12 +1098,12 @@ const multiLineSqlRules = async (combined, prevWords, currentWord, ctx, conn) =>
|
|
|
1096
1098
|
// Our scanner splits `(` and `,` as their own tokens (the C tokenizer
|
|
1097
1099
|
// keeps `(verbose` as one word), so `ends_with(prev_wd, '(')` becomes
|
|
1098
1100
|
// "previous token IS `(`" and similarly for `,`.
|
|
1099
|
-
if (HeadMatches(combined, [
|
|
1101
|
+
if (HeadMatches(combined, ["ANALYZE"]) &&
|
|
1100
1102
|
isInsideOpenParen(combined.slice(1))) {
|
|
1101
1103
|
const lastTok = combined[combined.length - 1];
|
|
1102
|
-
if (lastTok ===
|
|
1104
|
+
if (lastTok === "(" || lastTok === ",") {
|
|
1103
1105
|
return {
|
|
1104
|
-
candidates: filterAndCase([
|
|
1106
|
+
candidates: filterAndCase(["VERBOSE", "SKIP_LOCKED", "BUFFER_USAGE_LIMIT"], currentWord, ctx.settings),
|
|
1105
1107
|
};
|
|
1106
1108
|
}
|
|
1107
1109
|
// Inside the option list with a partial option name in the current
|
|
@@ -1109,13 +1111,13 @@ const multiLineSqlRules = async (combined, prevWords, currentWord, ctx, conn) =>
|
|
|
1109
1111
|
if (currentWord.length > 0 &&
|
|
1110
1112
|
(lastTok === undefined || /^[A-Za-z_]+$/.test(currentWord))) {
|
|
1111
1113
|
return {
|
|
1112
|
-
candidates: filterAndCase([
|
|
1114
|
+
candidates: filterAndCase(["VERBOSE", "SKIP_LOCKED", "BUFFER_USAGE_LIMIT"], currentWord, ctx.settings),
|
|
1113
1115
|
};
|
|
1114
1116
|
}
|
|
1115
1117
|
// `VERBOSE` / `SKIP_LOCKED` boolean continuation — ON / OFF.
|
|
1116
|
-
if (TailMatches(combined, [
|
|
1118
|
+
if (TailMatches(combined, ["VERBOSE|SKIP_LOCKED"])) {
|
|
1117
1119
|
return {
|
|
1118
|
-
candidates: filterAndCase([
|
|
1120
|
+
candidates: filterAndCase(["ON", "OFF"], currentWord, ctx.settings),
|
|
1119
1121
|
};
|
|
1120
1122
|
}
|
|
1121
1123
|
}
|
|
@@ -1128,7 +1130,7 @@ const multiLineSqlRules = async (combined, prevWords, currentWord, ctx, conn) =>
|
|
|
1128
1130
|
// We allow the rule to fire even when the line-local `prevWords` only
|
|
1129
1131
|
// sees the trailing `ON` — the COMBINED tokens carry the
|
|
1130
1132
|
// `COMMENT ON CONSTRAINT <name>` prefix from the previous line.
|
|
1131
|
-
if (TailMatches(combined, [
|
|
1133
|
+
if (TailMatches(combined, ["COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"])) {
|
|
1132
1134
|
if (!conn)
|
|
1133
1135
|
return { candidates: [] };
|
|
1134
1136
|
// `combined` ends in `ON`. The constraint name is the token just
|
|
@@ -1146,7 +1148,7 @@ const multiLineSqlRules = async (combined, prevWords, currentWord, ctx, conn) =>
|
|
|
1146
1148
|
? split.schema
|
|
1147
1149
|
: split.schema.toLowerCase();
|
|
1148
1150
|
return {
|
|
1149
|
-
candidates: rows.map((r) => canonicalSchema +
|
|
1151
|
+
candidates: rows.map((r) => canonicalSchema + "." + r),
|
|
1150
1152
|
};
|
|
1151
1153
|
}
|
|
1152
1154
|
// Unqualified: list tables that have the constraint, plus the schemas
|
|
@@ -1155,7 +1157,7 @@ const multiLineSqlRules = async (combined, prevWords, currentWord, ctx, conn) =>
|
|
|
1155
1157
|
runCatalogQuery(conn, Query_for_list_of_tables_for_constraint, currentWord, [constraintName]),
|
|
1156
1158
|
runCatalogQuery(conn, Query_for_list_of_schemas, currentWord),
|
|
1157
1159
|
]);
|
|
1158
|
-
return { candidates: [...tables, ...schemas.map((s) => s +
|
|
1160
|
+
return { candidates: [...tables, ...schemas.map((s) => s + ".")] };
|
|
1159
1161
|
}
|
|
1160
1162
|
void conn;
|
|
1161
1163
|
return null;
|
|
@@ -1171,11 +1173,11 @@ const isInsideOpenParen = (tokens) => {
|
|
|
1171
1173
|
let depth = 0;
|
|
1172
1174
|
let sawOpen = false;
|
|
1173
1175
|
for (const t of tokens) {
|
|
1174
|
-
if (t ===
|
|
1176
|
+
if (t === "(") {
|
|
1175
1177
|
depth++;
|
|
1176
1178
|
sawOpen = true;
|
|
1177
1179
|
}
|
|
1178
|
-
else if (t ===
|
|
1180
|
+
else if (t === ")") {
|
|
1179
1181
|
depth--;
|
|
1180
1182
|
}
|
|
1181
1183
|
}
|
|
@@ -1184,7 +1186,7 @@ const isInsideOpenParen = (tokens) => {
|
|
|
1184
1186
|
/** Strip surrounding `"..."` quoting from a constraint/identifier token. */
|
|
1185
1187
|
const stripIdentifierQuote = (raw) => {
|
|
1186
1188
|
if (raw === undefined)
|
|
1187
|
-
return
|
|
1189
|
+
return "";
|
|
1188
1190
|
if (raw.length >= 2 && raw.startsWith('"') && raw.endsWith('"')) {
|
|
1189
1191
|
return raw.slice(1, -1).replace(/""/g, '"');
|
|
1190
1192
|
}
|
|
@@ -1196,7 +1198,7 @@ const stripIdentifierQuote = (raw) => {
|
|
|
1196
1198
|
const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
1197
1199
|
const cmd = prevWords[0]; // e.g. '\dt'
|
|
1198
1200
|
// \c [DBNAME], \connect [DBNAME]: complete database names.
|
|
1199
|
-
if (cmd ===
|
|
1201
|
+
if (cmd === "\\c" || cmd === "\\connect") {
|
|
1200
1202
|
if (prevWords.length === 1 && conn) {
|
|
1201
1203
|
const rows = await runCatalogQuery(conn, Query_for_list_of_databases, currentWord);
|
|
1202
1204
|
return { candidates: rows };
|
|
@@ -1204,7 +1206,7 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1204
1206
|
return { candidates: [] };
|
|
1205
1207
|
}
|
|
1206
1208
|
// \dn[+] [schema]
|
|
1207
|
-
if (cmd ===
|
|
1209
|
+
if (cmd === "\\dn" || cmd === "\\dn+") {
|
|
1208
1210
|
if (prevWords.length === 1 && conn) {
|
|
1209
1211
|
const rows = await runCatalogQuery(conn, Query_for_list_of_schemas, currentWord);
|
|
1210
1212
|
return { candidates: rows };
|
|
@@ -1212,16 +1214,16 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1212
1214
|
return { candidates: [] };
|
|
1213
1215
|
}
|
|
1214
1216
|
// \df, \dfa, \dfn, \dfp, \dft, \dfw, \ef, \sf
|
|
1215
|
-
if (cmd ===
|
|
1216
|
-
cmd ===
|
|
1217
|
-
cmd ===
|
|
1218
|
-
cmd ===
|
|
1219
|
-
cmd ===
|
|
1220
|
-
cmd ===
|
|
1221
|
-
cmd ===
|
|
1222
|
-
cmd ===
|
|
1223
|
-
cmd ===
|
|
1224
|
-
cmd ===
|
|
1217
|
+
if (cmd === "\\df" ||
|
|
1218
|
+
cmd === "\\df+" ||
|
|
1219
|
+
cmd === "\\dfa" ||
|
|
1220
|
+
cmd === "\\dfn" ||
|
|
1221
|
+
cmd === "\\dfp" ||
|
|
1222
|
+
cmd === "\\dft" ||
|
|
1223
|
+
cmd === "\\dfw" ||
|
|
1224
|
+
cmd === "\\ef" ||
|
|
1225
|
+
cmd === "\\sf" ||
|
|
1226
|
+
cmd === "\\sf+") {
|
|
1225
1227
|
if (prevWords.length === 1 && conn) {
|
|
1226
1228
|
const rows = await runCatalogQuery(conn, Query_for_list_of_functions, currentWord);
|
|
1227
1229
|
return { candidates: rows };
|
|
@@ -1229,7 +1231,10 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1229
1231
|
return { candidates: [] };
|
|
1230
1232
|
}
|
|
1231
1233
|
// \du, \dg → roles.
|
|
1232
|
-
if (cmd ===
|
|
1234
|
+
if (cmd === "\\du" ||
|
|
1235
|
+
cmd === "\\dg" ||
|
|
1236
|
+
cmd === "\\du+" ||
|
|
1237
|
+
cmd === "\\dg+") {
|
|
1233
1238
|
if (prevWords.length === 1 && conn) {
|
|
1234
1239
|
const rows = await runCatalogQuery(conn, Query_for_list_of_roles, currentWord);
|
|
1235
1240
|
return { candidates: rows };
|
|
@@ -1237,7 +1242,7 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1237
1242
|
return { candidates: [] };
|
|
1238
1243
|
}
|
|
1239
1244
|
// \dx → extensions.
|
|
1240
|
-
if (cmd ===
|
|
1245
|
+
if (cmd === "\\dx" || cmd === "\\dx+") {
|
|
1241
1246
|
if (prevWords.length === 1 && conn) {
|
|
1242
1247
|
const rows = await runCatalogQuery(conn, Query_for_list_of_extensions, currentWord);
|
|
1243
1248
|
return { candidates: rows };
|
|
@@ -1245,7 +1250,7 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1245
1250
|
return { candidates: [] };
|
|
1246
1251
|
}
|
|
1247
1252
|
// \dL → languages.
|
|
1248
|
-
if (cmd ===
|
|
1253
|
+
if (cmd === "\\dL" || cmd === "\\dL+") {
|
|
1249
1254
|
if (prevWords.length === 1 && conn) {
|
|
1250
1255
|
const rows = await runCatalogQuery(conn, Query_for_list_of_languages, currentWord);
|
|
1251
1256
|
return { candidates: rows };
|
|
@@ -1253,7 +1258,7 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1253
1258
|
return { candidates: [] };
|
|
1254
1259
|
}
|
|
1255
1260
|
// \dT → types.
|
|
1256
|
-
if (cmd ===
|
|
1261
|
+
if (cmd === "\\dT" || cmd === "\\dT+") {
|
|
1257
1262
|
if (prevWords.length === 1 && conn) {
|
|
1258
1263
|
const rows = await runCatalogQuery(conn, Query_for_list_of_types, currentWord);
|
|
1259
1264
|
return { candidates: rows };
|
|
@@ -1261,10 +1266,10 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1261
1266
|
return { candidates: [] };
|
|
1262
1267
|
}
|
|
1263
1268
|
// \do → operators.
|
|
1264
|
-
if (cmd ===
|
|
1265
|
-
cmd ===
|
|
1266
|
-
cmd ===
|
|
1267
|
-
cmd ===
|
|
1269
|
+
if (cmd === "\\do" ||
|
|
1270
|
+
cmd === "\\do+" ||
|
|
1271
|
+
cmd === "\\doS" ||
|
|
1272
|
+
cmd === "\\doS+") {
|
|
1268
1273
|
if (prevWords.length === 1 && conn) {
|
|
1269
1274
|
const rows = await runCatalogQuery(conn, Query_for_list_of_operators, currentWord);
|
|
1270
1275
|
return { candidates: rows };
|
|
@@ -1272,7 +1277,7 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1272
1277
|
return { candidates: [] };
|
|
1273
1278
|
}
|
|
1274
1279
|
// \dC → casts (free-form pattern of "src AS tgt").
|
|
1275
|
-
if (cmd ===
|
|
1280
|
+
if (cmd === "\\dC" || cmd === "\\dC+") {
|
|
1276
1281
|
if (prevWords.length === 1 && conn) {
|
|
1277
1282
|
const rows = await runCatalogQuery(conn, Query_for_list_of_casts, currentWord);
|
|
1278
1283
|
return { candidates: rows };
|
|
@@ -1280,13 +1285,13 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1280
1285
|
return { candidates: [] };
|
|
1281
1286
|
}
|
|
1282
1287
|
// \dt / \dtv / \d / \dv / \dm / \di / \ds → relations of various kinds.
|
|
1283
|
-
if (cmd ===
|
|
1284
|
-
cmd ===
|
|
1285
|
-
cmd ===
|
|
1286
|
-
cmd ===
|
|
1287
|
-
cmd ===
|
|
1288
|
-
cmd ===
|
|
1289
|
-
cmd ===
|
|
1288
|
+
if (cmd === "\\dt" ||
|
|
1289
|
+
cmd === "\\dt+" ||
|
|
1290
|
+
cmd === "\\dtv" ||
|
|
1291
|
+
cmd === "\\d" ||
|
|
1292
|
+
cmd === "\\d+" ||
|
|
1293
|
+
cmd === "\\dE" ||
|
|
1294
|
+
cmd === "\\dE+") {
|
|
1290
1295
|
if (prevWords.length === 1 && conn) {
|
|
1291
1296
|
return {
|
|
1292
1297
|
candidates: await completeSchemaOrRelations(conn, currentWord, Query_for_list_of_tables),
|
|
@@ -1294,7 +1299,7 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1294
1299
|
}
|
|
1295
1300
|
return { candidates: [] };
|
|
1296
1301
|
}
|
|
1297
|
-
if (cmd ===
|
|
1302
|
+
if (cmd === "\\dv" || cmd === "\\dv+") {
|
|
1298
1303
|
if (prevWords.length === 1 && conn) {
|
|
1299
1304
|
return {
|
|
1300
1305
|
candidates: await completeSchemaOrRelations(conn, currentWord, Query_for_list_of_views),
|
|
@@ -1302,7 +1307,7 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1302
1307
|
}
|
|
1303
1308
|
return { candidates: [] };
|
|
1304
1309
|
}
|
|
1305
|
-
if (cmd ===
|
|
1310
|
+
if (cmd === "\\dm" || cmd === "\\dm+") {
|
|
1306
1311
|
if (prevWords.length === 1 && conn) {
|
|
1307
1312
|
return {
|
|
1308
1313
|
candidates: await completeSchemaOrRelations(conn, currentWord, Query_for_list_of_matviews),
|
|
@@ -1310,7 +1315,7 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1310
1315
|
}
|
|
1311
1316
|
return { candidates: [] };
|
|
1312
1317
|
}
|
|
1313
|
-
if (cmd ===
|
|
1318
|
+
if (cmd === "\\di" || cmd === "\\di+") {
|
|
1314
1319
|
if (prevWords.length === 1 && conn) {
|
|
1315
1320
|
return {
|
|
1316
1321
|
candidates: await completeSchemaOrRelations(conn, currentWord, Query_for_list_of_indexes),
|
|
@@ -1318,7 +1323,7 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1318
1323
|
}
|
|
1319
1324
|
return { candidates: [] };
|
|
1320
1325
|
}
|
|
1321
|
-
if (cmd ===
|
|
1326
|
+
if (cmd === "\\ds" || cmd === "\\ds+") {
|
|
1322
1327
|
if (prevWords.length === 1 && conn) {
|
|
1323
1328
|
return {
|
|
1324
1329
|
candidates: await completeSchemaOrRelations(conn, currentWord, Query_for_list_of_sequences),
|
|
@@ -1327,10 +1332,10 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1327
1332
|
return { candidates: [] };
|
|
1328
1333
|
}
|
|
1329
1334
|
// \l[+] / \list → databases.
|
|
1330
|
-
if (cmd ===
|
|
1331
|
-
cmd ===
|
|
1332
|
-
cmd ===
|
|
1333
|
-
cmd ===
|
|
1335
|
+
if (cmd === "\\l" ||
|
|
1336
|
+
cmd === "\\l+" ||
|
|
1337
|
+
cmd === "\\list" ||
|
|
1338
|
+
cmd === "\\list+") {
|
|
1334
1339
|
if (prevWords.length === 1 && conn) {
|
|
1335
1340
|
const rows = await runCatalogQuery(conn, Query_for_list_of_databases, currentWord);
|
|
1336
1341
|
return { candidates: rows };
|
|
@@ -1338,14 +1343,14 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1338
1343
|
return { candidates: [] };
|
|
1339
1344
|
}
|
|
1340
1345
|
// \encoding NAME
|
|
1341
|
-
if (cmd ===
|
|
1346
|
+
if (cmd === "\\encoding") {
|
|
1342
1347
|
if (prevWords.length === 1) {
|
|
1343
1348
|
return { candidates: filterCi(ENCODINGS, currentWord) };
|
|
1344
1349
|
}
|
|
1345
1350
|
return { candidates: [] };
|
|
1346
1351
|
}
|
|
1347
1352
|
// \pset OPT [value]
|
|
1348
|
-
if (cmd ===
|
|
1353
|
+
if (cmd === "\\pset") {
|
|
1349
1354
|
if (prevWords.length === 1) {
|
|
1350
1355
|
return { candidates: filterCi(PSET_OPTIONS, currentWord) };
|
|
1351
1356
|
}
|
|
@@ -1358,7 +1363,7 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1358
1363
|
return { candidates: [] };
|
|
1359
1364
|
}
|
|
1360
1365
|
// \set NAME [VALUE]
|
|
1361
|
-
if (cmd ===
|
|
1366
|
+
if (cmd === "\\set") {
|
|
1362
1367
|
if (prevWords.length === 1) {
|
|
1363
1368
|
return {
|
|
1364
1369
|
candidates: filterCi(listAllVarNames(ctx.settings), currentWord),
|
|
@@ -1373,15 +1378,17 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1373
1378
|
return { candidates: [] };
|
|
1374
1379
|
}
|
|
1375
1380
|
// \unset NAME — only existing variables.
|
|
1376
|
-
if (cmd ===
|
|
1381
|
+
if (cmd === "\\unset") {
|
|
1377
1382
|
if (prevWords.length === 1) {
|
|
1378
|
-
return {
|
|
1383
|
+
return {
|
|
1384
|
+
candidates: filterCi(listVarNames(ctx.settings), currentWord),
|
|
1385
|
+
};
|
|
1379
1386
|
}
|
|
1380
1387
|
return { candidates: [] };
|
|
1381
1388
|
}
|
|
1382
1389
|
// \echo / \warn / \qecho — variable expansion only (handled above).
|
|
1383
1390
|
// \prompt — variable name argument is the 1st positional.
|
|
1384
|
-
if (cmd ===
|
|
1391
|
+
if (cmd === "\\prompt") {
|
|
1385
1392
|
if (prevWords.length === 2) {
|
|
1386
1393
|
return {
|
|
1387
1394
|
candidates: filterCi(listAllVarNames(ctx.settings), currentWord),
|
|
@@ -1392,16 +1399,16 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1392
1399
|
// \lo_import / \lo_export → filesystem-driven filename completion.
|
|
1393
1400
|
// psql parses the path as a backslash-argument literal — no SQL string
|
|
1394
1401
|
// quoting required, so we use the unquoted candidate form.
|
|
1395
|
-
if (cmd ===
|
|
1402
|
+
if (cmd === "\\lo_import" || cmd === "\\lo_export") {
|
|
1396
1403
|
if (prevWords.length === 1) {
|
|
1397
|
-
return { candidates: completeFilenames(currentWord,
|
|
1404
|
+
return { candidates: completeFilenames(currentWord, "none") };
|
|
1398
1405
|
}
|
|
1399
1406
|
return { candidates: [] };
|
|
1400
1407
|
}
|
|
1401
1408
|
// \copy <table> [FROM|TO] <path> — once the FROM/TO keyword has been
|
|
1402
1409
|
// typed, the next token is a filename (backslash-context, so bare paths
|
|
1403
1410
|
// are fine).
|
|
1404
|
-
if (cmd ===
|
|
1411
|
+
if (cmd === "\\copy") {
|
|
1405
1412
|
// First arg: a table name.
|
|
1406
1413
|
if (prevWords.length === 1 && conn) {
|
|
1407
1414
|
return {
|
|
@@ -1411,20 +1418,20 @@ const backslashArgRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1411
1418
|
// Second arg: the FROM/TO keyword.
|
|
1412
1419
|
if (prevWords.length === 2) {
|
|
1413
1420
|
return {
|
|
1414
|
-
candidates: filterAndCase([
|
|
1421
|
+
candidates: filterAndCase(["FROM", "TO"], currentWord, ctx.settings),
|
|
1415
1422
|
};
|
|
1416
1423
|
}
|
|
1417
1424
|
// Third arg (after FROM/TO): the filename.
|
|
1418
1425
|
if (prevWords.length >= 3) {
|
|
1419
1426
|
const last = prevWords[prevWords.length - 1].toUpperCase();
|
|
1420
|
-
if (last ===
|
|
1421
|
-
return { candidates: completeFilenames(currentWord,
|
|
1427
|
+
if (last === "FROM" || last === "TO") {
|
|
1428
|
+
return { candidates: completeFilenames(currentWord, "none") };
|
|
1422
1429
|
}
|
|
1423
1430
|
}
|
|
1424
1431
|
return { candidates: [] };
|
|
1425
1432
|
}
|
|
1426
1433
|
// \drds, \drg → roles (for the first arg).
|
|
1427
|
-
if (cmd ===
|
|
1434
|
+
if (cmd === "\\drds" || cmd === "\\drg") {
|
|
1428
1435
|
if (prevWords.length === 1 && conn) {
|
|
1429
1436
|
const rows = await runCatalogQuery(conn, Query_for_list_of_roles, currentWord);
|
|
1430
1437
|
return { candidates: rows };
|
|
@@ -1451,34 +1458,35 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1451
1458
|
// string-literal context. MUST come before the generic `FROM <prefix>`
|
|
1452
1459
|
// rule below, which would otherwise treat the path as a table name.
|
|
1453
1460
|
if (isCopyFromOrTo(prevWords)) {
|
|
1454
|
-
return { candidates: completeFilenames(currentWord,
|
|
1461
|
+
return { candidates: completeFilenames(currentWord, "sql") };
|
|
1455
1462
|
}
|
|
1456
1463
|
// FROM <prefix>: tables/views/matviews. EXCLUDE `REVOKE … FROM <role>`,
|
|
1457
1464
|
// which must complete role names — otherwise this generic rule shadows the
|
|
1458
1465
|
// REVOKE-roles arm below, making it dead code (review item #26).
|
|
1459
|
-
if (TailMatches(prevWords, [
|
|
1466
|
+
if (TailMatches(prevWords, ["FROM"]) &&
|
|
1467
|
+
!HeadMatches(prevWords, ["REVOKE"])) {
|
|
1460
1468
|
return completeTables(Query_for_list_of_tables_views);
|
|
1461
1469
|
}
|
|
1462
1470
|
// After FROM x, suggest JOIN/WHERE/etc — handled below.
|
|
1463
1471
|
// UPDATE <prefix>: tables.
|
|
1464
|
-
if (TailMatches(prevWords, [
|
|
1472
|
+
if (TailMatches(prevWords, ["UPDATE"]))
|
|
1465
1473
|
return completeTables();
|
|
1466
1474
|
// DELETE FROM <prefix>: tables.
|
|
1467
|
-
if (TailMatches(prevWords, [
|
|
1475
|
+
if (TailMatches(prevWords, ["DELETE", "FROM"]))
|
|
1468
1476
|
return completeTables();
|
|
1469
1477
|
// INSERT INTO <prefix>: tables. The tokenizer might give us
|
|
1470
1478
|
// ['INSERT'] [INTO] or ['INSERT', 'INTO'] depending on whether the user
|
|
1471
1479
|
// typed an extra space.
|
|
1472
|
-
if (TailMatches(prevWords, [
|
|
1480
|
+
if (TailMatches(prevWords, ["INTO"]))
|
|
1473
1481
|
return completeTables();
|
|
1474
1482
|
// JOIN <prefix>: tables. Most common: SELECT … FROM x JOIN <prefix>.
|
|
1475
|
-
if (TailMatches(prevWords, [
|
|
1483
|
+
if (TailMatches(prevWords, ["JOIN"])) {
|
|
1476
1484
|
return completeTables(Query_for_list_of_tables_views);
|
|
1477
1485
|
}
|
|
1478
1486
|
// After JOIN x, suggest ON or USING.
|
|
1479
|
-
if (TailMatches(prevWords, [
|
|
1487
|
+
if (TailMatches(prevWords, ["JOIN", MatchAny])) {
|
|
1480
1488
|
return {
|
|
1481
|
-
candidates: filterAndCase([
|
|
1489
|
+
candidates: filterAndCase(["ON", "USING"], currentWord, ctx.settings),
|
|
1482
1490
|
};
|
|
1483
1491
|
}
|
|
1484
1492
|
// After `FROM table_name <TAB>` (or `FROM table AS alias <TAB>`) — offer
|
|
@@ -1486,15 +1494,15 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1486
1494
|
// SELECT/INSERT/UPDATE/DELETE (i.e. a SELECT-list-friendly context), so
|
|
1487
1495
|
// we don't trample more specific rules like `ALTER TABLE x` or
|
|
1488
1496
|
// `INSERT INTO x` which look "FROM-like" structurally.
|
|
1489
|
-
const inSelectContext = HeadMatches(prevWords, [
|
|
1490
|
-
HeadMatches(prevWords, [
|
|
1491
|
-
HeadMatches(prevWords, [
|
|
1492
|
-
HeadMatches(prevWords, [
|
|
1493
|
-
HeadMatches(prevWords, [
|
|
1494
|
-
HeadMatches(prevWords, [
|
|
1497
|
+
const inSelectContext = HeadMatches(prevWords, ["SELECT"]) ||
|
|
1498
|
+
HeadMatches(prevWords, ["INSERT"]) ||
|
|
1499
|
+
HeadMatches(prevWords, ["UPDATE"]) ||
|
|
1500
|
+
HeadMatches(prevWords, ["DELETE"]) ||
|
|
1501
|
+
HeadMatches(prevWords, ["WITH"]) ||
|
|
1502
|
+
HeadMatches(prevWords, ["EXPLAIN"]);
|
|
1495
1503
|
if (inSelectContext &&
|
|
1496
|
-
(TailMatches(prevWords, [
|
|
1497
|
-
TailMatches(prevWords, [
|
|
1504
|
+
(TailMatches(prevWords, ["FROM", MatchAny]) ||
|
|
1505
|
+
TailMatches(prevWords, ["FROM", MatchAny, MatchAny]))) {
|
|
1498
1506
|
// `FROM x` or `FROM x alias` → post-FROM continuations.
|
|
1499
1507
|
return {
|
|
1500
1508
|
candidates: filterAndCase(POST_FROM_KEYWORDS, currentWord, ctx.settings),
|
|
@@ -1502,7 +1510,7 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1502
1510
|
}
|
|
1503
1511
|
// Window-function frame clause: `OVER (` then `<TAB>`. The tokenizer
|
|
1504
1512
|
// emits the `(` as its own token, so prevWords ends with '('.
|
|
1505
|
-
if (TailMatches(prevWords, [
|
|
1513
|
+
if (TailMatches(prevWords, ["OVER", "("])) {
|
|
1506
1514
|
return {
|
|
1507
1515
|
candidates: filterAndCase(WINDOW_FRAME_KEYWORDS, currentWord, ctx.settings),
|
|
1508
1516
|
};
|
|
@@ -1512,8 +1520,8 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1512
1520
|
// suggest boolean continuations. We trigger on the simple case
|
|
1513
1521
|
// `WHERE <ident>` and `WHERE … AND/OR <ident>`.
|
|
1514
1522
|
if (inSelectContext &&
|
|
1515
|
-
TailMatches(prevWords, [
|
|
1516
|
-
!TailMatches(prevWords, [
|
|
1523
|
+
TailMatches(prevWords, ["WHERE", MatchAny]) &&
|
|
1524
|
+
!TailMatches(prevWords, ["WHERE"])) {
|
|
1517
1525
|
return {
|
|
1518
1526
|
candidates: filterAndCase(WHERE_CONTINUATIONS, currentWord, ctx.settings),
|
|
1519
1527
|
};
|
|
@@ -1523,14 +1531,14 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1523
1531
|
// 3-token fallback `ALTER TABLE x` (which lists generic sub-actions).
|
|
1524
1532
|
// The deeper rules use HeadMatches so they survive an arbitrary trailing
|
|
1525
1533
|
// option list like `ALTER TABLE foo ADD CONSTRAINT bar CHECK (...)`.
|
|
1526
|
-
if (HeadMatches(prevWords, [
|
|
1527
|
-
TailMatches(prevWords, [
|
|
1534
|
+
if (HeadMatches(prevWords, ["ALTER", "TABLE"]) &&
|
|
1535
|
+
TailMatches(prevWords, ["ADD"])) {
|
|
1528
1536
|
return {
|
|
1529
1537
|
candidates: filterAndCase(ALTER_TABLE_ADD, currentWord, ctx.settings),
|
|
1530
1538
|
};
|
|
1531
1539
|
}
|
|
1532
|
-
if (HeadMatches(prevWords, [
|
|
1533
|
-
TailMatches(prevWords, [
|
|
1540
|
+
if (HeadMatches(prevWords, ["ALTER", "TABLE"]) &&
|
|
1541
|
+
TailMatches(prevWords, ["DROP"])) {
|
|
1534
1542
|
return {
|
|
1535
1543
|
candidates: filterAndCase(ALTER_TABLE_DROP, currentWord, ctx.settings),
|
|
1536
1544
|
};
|
|
@@ -1538,8 +1546,8 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1538
1546
|
// `ALTER TABLE <ref> DROP CONSTRAINT <prefix>` — constraint names on
|
|
1539
1547
|
// the referenced table. Mirrors upstream tab-complete.in.c ~line 1280
|
|
1540
1548
|
// (`COMPLETE_WITH_QUERY(Query_for_constraint_of_table)`).
|
|
1541
|
-
if (HeadMatches(prevWords, [
|
|
1542
|
-
TailMatches(prevWords, [
|
|
1549
|
+
if (HeadMatches(prevWords, ["ALTER", "TABLE"]) &&
|
|
1550
|
+
TailMatches(prevWords, ["DROP", "CONSTRAINT"])) {
|
|
1543
1551
|
if (!conn)
|
|
1544
1552
|
return { candidates: [] };
|
|
1545
1553
|
const refTokens = prevWords.slice(2, prevWords.length - 2);
|
|
@@ -1551,94 +1559,98 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1551
1559
|
: await runCatalogQuery(conn, Query_for_constraint_of_table_in_schema, currentWord, [ref.schema, ref.table]);
|
|
1552
1560
|
return { candidates: cands };
|
|
1553
1561
|
}
|
|
1554
|
-
if (HeadMatches(prevWords, [
|
|
1555
|
-
TailMatches(prevWords, [
|
|
1562
|
+
if (HeadMatches(prevWords, ["ALTER", "TABLE"]) &&
|
|
1563
|
+
TailMatches(prevWords, ["RENAME"])) {
|
|
1556
1564
|
return {
|
|
1557
1565
|
candidates: filterAndCase(ALTER_TABLE_RENAME, currentWord, ctx.settings),
|
|
1558
1566
|
};
|
|
1559
1567
|
}
|
|
1560
|
-
if (HeadMatches(prevWords, [
|
|
1561
|
-
(TailMatches(prevWords, [
|
|
1562
|
-
TailMatches(prevWords, [
|
|
1568
|
+
if (HeadMatches(prevWords, ["ALTER", "TABLE"]) &&
|
|
1569
|
+
(TailMatches(prevWords, ["ALTER"]) ||
|
|
1570
|
+
TailMatches(prevWords, ["ALTER", "COLUMN", MatchAny]))) {
|
|
1563
1571
|
return {
|
|
1564
1572
|
candidates: filterAndCase(ALTER_TABLE_ALTER_COLUMN, currentWord, ctx.settings),
|
|
1565
1573
|
};
|
|
1566
1574
|
}
|
|
1567
|
-
if (HeadMatches(prevWords, [
|
|
1568
|
-
TailMatches(prevWords, [
|
|
1575
|
+
if (HeadMatches(prevWords, ["ALTER", "TABLE"]) &&
|
|
1576
|
+
TailMatches(prevWords, ["SET"])) {
|
|
1569
1577
|
return {
|
|
1570
1578
|
candidates: filterAndCase(ALTER_TABLE_SET, currentWord, ctx.settings),
|
|
1571
1579
|
};
|
|
1572
1580
|
}
|
|
1573
|
-
if (HeadMatches(prevWords, [
|
|
1574
|
-
TailMatches(prevWords, [
|
|
1581
|
+
if (HeadMatches(prevWords, ["ALTER", "TABLE"]) &&
|
|
1582
|
+
TailMatches(prevWords, ["ENABLE"])) {
|
|
1575
1583
|
return {
|
|
1576
1584
|
candidates: filterAndCase(ALTER_TABLE_ENABLE, currentWord, ctx.settings),
|
|
1577
1585
|
};
|
|
1578
1586
|
}
|
|
1579
|
-
if (HeadMatches(prevWords, [
|
|
1580
|
-
TailMatches(prevWords, [
|
|
1587
|
+
if (HeadMatches(prevWords, ["ALTER", "TABLE"]) &&
|
|
1588
|
+
TailMatches(prevWords, ["DISABLE"])) {
|
|
1581
1589
|
return {
|
|
1582
1590
|
candidates: filterAndCase(ALTER_TABLE_DISABLE, currentWord, ctx.settings),
|
|
1583
1591
|
};
|
|
1584
1592
|
}
|
|
1585
|
-
if (HeadMatches(prevWords, [
|
|
1586
|
-
TailMatches(prevWords, [
|
|
1593
|
+
if (HeadMatches(prevWords, ["ALTER", "TABLE"]) &&
|
|
1594
|
+
TailMatches(prevWords, ["REPLICA", "IDENTITY"])) {
|
|
1587
1595
|
return {
|
|
1588
1596
|
candidates: filterAndCase(ALTER_TABLE_REPLICA_IDENTITY, currentWord, ctx.settings),
|
|
1589
1597
|
};
|
|
1590
1598
|
}
|
|
1591
1599
|
// ALTER TABLE x — sub-actions (must come AFTER the deep continuations above).
|
|
1592
|
-
if (TailMatches(prevWords, [
|
|
1600
|
+
if (TailMatches(prevWords, ["ALTER", "TABLE", MatchAny])) {
|
|
1593
1601
|
return {
|
|
1594
1602
|
candidates: filterAndCase(ALTER_TABLE_ACTIONS, currentWord, ctx.settings),
|
|
1595
1603
|
};
|
|
1596
1604
|
}
|
|
1597
1605
|
// ALTER TABLE — table name.
|
|
1598
|
-
if (TailMatches(prevWords, [
|
|
1606
|
+
if (TailMatches(prevWords, ["ALTER", "TABLE"]))
|
|
1599
1607
|
return completeTables();
|
|
1600
1608
|
// ---- ALTER VIEW / MATERIALIZED VIEW ----
|
|
1601
|
-
if (TailMatches(prevWords, [
|
|
1609
|
+
if (TailMatches(prevWords, ["ALTER", "VIEW", MatchAny])) {
|
|
1602
1610
|
return {
|
|
1603
1611
|
candidates: filterAndCase(ALTER_VIEW_ACTIONS, currentWord, ctx.settings),
|
|
1604
1612
|
};
|
|
1605
1613
|
}
|
|
1606
|
-
if (TailMatches(prevWords, [
|
|
1614
|
+
if (TailMatches(prevWords, ["ALTER", "VIEW"])) {
|
|
1607
1615
|
return completeTables(Query_for_list_of_views);
|
|
1608
1616
|
}
|
|
1609
|
-
if (TailMatches(prevWords, [
|
|
1617
|
+
if (TailMatches(prevWords, ["ALTER", "MATERIALIZED", "VIEW", MatchAny])) {
|
|
1610
1618
|
return {
|
|
1611
1619
|
candidates: filterAndCase(ALTER_MATVIEW_ACTIONS, currentWord, ctx.settings),
|
|
1612
1620
|
};
|
|
1613
1621
|
}
|
|
1614
|
-
if (TailMatches(prevWords, [
|
|
1622
|
+
if (TailMatches(prevWords, ["ALTER", "MATERIALIZED", "VIEW"])) {
|
|
1615
1623
|
return completeTables(Query_for_list_of_matviews);
|
|
1616
1624
|
}
|
|
1617
1625
|
// ---- ALTER INDEX ----
|
|
1618
|
-
if (TailMatches(prevWords, [
|
|
1626
|
+
if (TailMatches(prevWords, ["ALTER", "INDEX", MatchAny])) {
|
|
1619
1627
|
return {
|
|
1620
1628
|
candidates: filterAndCase(ALTER_INDEX_ACTIONS, currentWord, ctx.settings),
|
|
1621
1629
|
};
|
|
1622
1630
|
}
|
|
1623
|
-
if (TailMatches(prevWords, [
|
|
1631
|
+
if (TailMatches(prevWords, ["ALTER", "INDEX"])) {
|
|
1624
1632
|
return completeTables(Query_for_list_of_indexes);
|
|
1625
1633
|
}
|
|
1626
1634
|
// ---- ALTER SEQUENCE ----
|
|
1627
|
-
if (TailMatches(prevWords, [
|
|
1635
|
+
if (TailMatches(prevWords, ["ALTER", "SEQUENCE", MatchAny])) {
|
|
1628
1636
|
return {
|
|
1629
1637
|
candidates: filterAndCase(ALTER_SEQUENCE_ACTIONS, currentWord, ctx.settings),
|
|
1630
1638
|
};
|
|
1631
1639
|
}
|
|
1632
|
-
if (TailMatches(prevWords, [
|
|
1640
|
+
if (TailMatches(prevWords, ["ALTER", "SEQUENCE"])) {
|
|
1633
1641
|
return completeTables(Query_for_list_of_sequences);
|
|
1634
1642
|
}
|
|
1635
1643
|
// ---- ALTER FUNCTION / PROCEDURE / ROUTINE ----
|
|
1636
|
-
if (TailMatches(prevWords, [
|
|
1644
|
+
if (TailMatches(prevWords, [
|
|
1645
|
+
"ALTER",
|
|
1646
|
+
"FUNCTION|PROCEDURE|ROUTINE",
|
|
1647
|
+
MatchAny,
|
|
1648
|
+
])) {
|
|
1637
1649
|
return {
|
|
1638
1650
|
candidates: filterAndCase(ALTER_FUNCTION_ACTIONS, currentWord, ctx.settings),
|
|
1639
1651
|
};
|
|
1640
1652
|
}
|
|
1641
|
-
if (TailMatches(prevWords, [
|
|
1653
|
+
if (TailMatches(prevWords, ["ALTER", "FUNCTION|PROCEDURE|ROUTINE"])) {
|
|
1642
1654
|
if (!conn)
|
|
1643
1655
|
return { candidates: [] };
|
|
1644
1656
|
return {
|
|
@@ -1649,7 +1661,13 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1649
1661
|
// `ALTER TYPE <enum> RENAME VALUE 'X<TAB>` — enum labels of the named
|
|
1650
1662
|
// type, wrapped in single quotes since the user is mid-string-literal.
|
|
1651
1663
|
// Mirrors upstream tab-complete.in.c ~line 1480.
|
|
1652
|
-
if (TailMatches(prevWords, [
|
|
1664
|
+
if (TailMatches(prevWords, [
|
|
1665
|
+
"ALTER",
|
|
1666
|
+
"TYPE",
|
|
1667
|
+
MatchAny,
|
|
1668
|
+
"RENAME",
|
|
1669
|
+
"VALUE",
|
|
1670
|
+
]) &&
|
|
1653
1671
|
currentWord.startsWith("'")) {
|
|
1654
1672
|
if (!conn)
|
|
1655
1673
|
return { candidates: [] };
|
|
@@ -1660,12 +1678,12 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1660
1678
|
const cands = await runCatalogQuery(conn, Query_for_list_of_enum_values_quoted, labelPrefix, [typeName]);
|
|
1661
1679
|
return { candidates: cands };
|
|
1662
1680
|
}
|
|
1663
|
-
if (TailMatches(prevWords, [
|
|
1681
|
+
if (TailMatches(prevWords, ["ALTER", "TYPE", MatchAny])) {
|
|
1664
1682
|
return {
|
|
1665
1683
|
candidates: filterAndCase(ALTER_TYPE_ACTIONS, currentWord, ctx.settings),
|
|
1666
1684
|
};
|
|
1667
1685
|
}
|
|
1668
|
-
if (TailMatches(prevWords, [
|
|
1686
|
+
if (TailMatches(prevWords, ["ALTER", "TYPE"])) {
|
|
1669
1687
|
if (!conn)
|
|
1670
1688
|
return { candidates: [] };
|
|
1671
1689
|
return {
|
|
@@ -1673,12 +1691,12 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1673
1691
|
};
|
|
1674
1692
|
}
|
|
1675
1693
|
// ---- ALTER ROLE / USER / GROUP ----
|
|
1676
|
-
if (TailMatches(prevWords, [
|
|
1694
|
+
if (TailMatches(prevWords, ["ALTER", "ROLE|USER|GROUP", MatchAny])) {
|
|
1677
1695
|
return {
|
|
1678
1696
|
candidates: filterAndCase(ALTER_ROLE_ACTIONS, currentWord, ctx.settings),
|
|
1679
1697
|
};
|
|
1680
1698
|
}
|
|
1681
|
-
if (TailMatches(prevWords, [
|
|
1699
|
+
if (TailMatches(prevWords, ["ALTER", "ROLE|USER|GROUP"])) {
|
|
1682
1700
|
if (!conn)
|
|
1683
1701
|
return { candidates: [] };
|
|
1684
1702
|
return {
|
|
@@ -1686,12 +1704,12 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1686
1704
|
};
|
|
1687
1705
|
}
|
|
1688
1706
|
// ---- ALTER DATABASE ----
|
|
1689
|
-
if (TailMatches(prevWords, [
|
|
1707
|
+
if (TailMatches(prevWords, ["ALTER", "DATABASE", MatchAny])) {
|
|
1690
1708
|
return {
|
|
1691
1709
|
candidates: filterAndCase(ALTER_DATABASE_ACTIONS, currentWord, ctx.settings),
|
|
1692
1710
|
};
|
|
1693
1711
|
}
|
|
1694
|
-
if (TailMatches(prevWords, [
|
|
1712
|
+
if (TailMatches(prevWords, ["ALTER", "DATABASE"])) {
|
|
1695
1713
|
if (!conn)
|
|
1696
1714
|
return { candidates: [] };
|
|
1697
1715
|
return {
|
|
@@ -1699,12 +1717,12 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1699
1717
|
};
|
|
1700
1718
|
}
|
|
1701
1719
|
// ---- ALTER SCHEMA ----
|
|
1702
|
-
if (TailMatches(prevWords, [
|
|
1720
|
+
if (TailMatches(prevWords, ["ALTER", "SCHEMA", MatchAny])) {
|
|
1703
1721
|
return {
|
|
1704
1722
|
candidates: filterAndCase(ALTER_SCHEMA_ACTIONS, currentWord, ctx.settings),
|
|
1705
1723
|
};
|
|
1706
1724
|
}
|
|
1707
|
-
if (TailMatches(prevWords, [
|
|
1725
|
+
if (TailMatches(prevWords, ["ALTER", "SCHEMA"])) {
|
|
1708
1726
|
if (!conn)
|
|
1709
1727
|
return { candidates: [] };
|
|
1710
1728
|
return {
|
|
@@ -1712,12 +1730,12 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1712
1730
|
};
|
|
1713
1731
|
}
|
|
1714
1732
|
// ---- ALTER EXTENSION ----
|
|
1715
|
-
if (TailMatches(prevWords, [
|
|
1733
|
+
if (TailMatches(prevWords, ["ALTER", "EXTENSION", MatchAny])) {
|
|
1716
1734
|
return {
|
|
1717
1735
|
candidates: filterAndCase(ALTER_EXTENSION_ACTIONS, currentWord, ctx.settings),
|
|
1718
1736
|
};
|
|
1719
1737
|
}
|
|
1720
|
-
if (TailMatches(prevWords, [
|
|
1738
|
+
if (TailMatches(prevWords, ["ALTER", "EXTENSION"])) {
|
|
1721
1739
|
if (!conn)
|
|
1722
1740
|
return { candidates: [] };
|
|
1723
1741
|
return {
|
|
@@ -1725,26 +1743,26 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1725
1743
|
};
|
|
1726
1744
|
}
|
|
1727
1745
|
// ---- ALTER POLICY <name> ON <table> ----
|
|
1728
|
-
if (TailMatches(prevWords, [
|
|
1746
|
+
if (TailMatches(prevWords, ["ALTER", "POLICY", MatchAny])) {
|
|
1729
1747
|
return {
|
|
1730
1748
|
candidates: filterAndCase(ALTER_POLICY_ACTIONS, currentWord, ctx.settings),
|
|
1731
1749
|
};
|
|
1732
1750
|
}
|
|
1733
|
-
if (HeadMatches(prevWords, [
|
|
1734
|
-
TailMatches(prevWords, [
|
|
1751
|
+
if (HeadMatches(prevWords, ["ALTER", "POLICY"]) &&
|
|
1752
|
+
TailMatches(prevWords, ["ON"])) {
|
|
1735
1753
|
return completeTables();
|
|
1736
1754
|
}
|
|
1737
|
-
if (TailMatches(prevWords, [
|
|
1755
|
+
if (TailMatches(prevWords, ["ALTER", "POLICY"])) {
|
|
1738
1756
|
// Free-form policy name.
|
|
1739
1757
|
return { candidates: [] };
|
|
1740
1758
|
}
|
|
1741
1759
|
// ---- ALTER PUBLICATION ----
|
|
1742
|
-
if (TailMatches(prevWords, [
|
|
1760
|
+
if (TailMatches(prevWords, ["ALTER", "PUBLICATION", MatchAny])) {
|
|
1743
1761
|
return {
|
|
1744
1762
|
candidates: filterAndCase(ALTER_PUBLICATION_ACTIONS, currentWord, ctx.settings),
|
|
1745
1763
|
};
|
|
1746
1764
|
}
|
|
1747
|
-
if (TailMatches(prevWords, [
|
|
1765
|
+
if (TailMatches(prevWords, ["ALTER", "PUBLICATION"])) {
|
|
1748
1766
|
if (!conn)
|
|
1749
1767
|
return { candidates: [] };
|
|
1750
1768
|
return {
|
|
@@ -1752,12 +1770,12 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1752
1770
|
};
|
|
1753
1771
|
}
|
|
1754
1772
|
// ---- ALTER SUBSCRIPTION ----
|
|
1755
|
-
if (TailMatches(prevWords, [
|
|
1773
|
+
if (TailMatches(prevWords, ["ALTER", "SUBSCRIPTION", MatchAny])) {
|
|
1756
1774
|
return {
|
|
1757
1775
|
candidates: filterAndCase(ALTER_SUBSCRIPTION_ACTIONS, currentWord, ctx.settings),
|
|
1758
1776
|
};
|
|
1759
1777
|
}
|
|
1760
|
-
if (TailMatches(prevWords, [
|
|
1778
|
+
if (TailMatches(prevWords, ["ALTER", "SUBSCRIPTION"])) {
|
|
1761
1779
|
if (!conn)
|
|
1762
1780
|
return { candidates: [] };
|
|
1763
1781
|
return {
|
|
@@ -1765,27 +1783,27 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1765
1783
|
};
|
|
1766
1784
|
}
|
|
1767
1785
|
// Bare ALTER — sub-object keywords.
|
|
1768
|
-
if (TailMatches(prevWords, [
|
|
1786
|
+
if (TailMatches(prevWords, ["ALTER"])) {
|
|
1769
1787
|
return {
|
|
1770
1788
|
candidates: filterAndCase(ALTER_OBJECTS, currentWord, ctx.settings),
|
|
1771
1789
|
};
|
|
1772
1790
|
}
|
|
1773
1791
|
// DROP TABLE, DROP VIEW, DROP INDEX, ...
|
|
1774
|
-
if (TailMatches(prevWords, [
|
|
1792
|
+
if (TailMatches(prevWords, ["DROP", "TABLE"]))
|
|
1775
1793
|
return completeTables();
|
|
1776
|
-
if (TailMatches(prevWords, [
|
|
1794
|
+
if (TailMatches(prevWords, ["DROP", "VIEW"])) {
|
|
1777
1795
|
return completeTables(Query_for_list_of_views);
|
|
1778
1796
|
}
|
|
1779
|
-
if (TailMatches(prevWords, [
|
|
1797
|
+
if (TailMatches(prevWords, ["DROP", "MATERIALIZED", "VIEW"])) {
|
|
1780
1798
|
return completeTables(Query_for_list_of_matviews);
|
|
1781
1799
|
}
|
|
1782
|
-
if (TailMatches(prevWords, [
|
|
1800
|
+
if (TailMatches(prevWords, ["DROP", "INDEX"])) {
|
|
1783
1801
|
return completeTables(Query_for_list_of_indexes);
|
|
1784
1802
|
}
|
|
1785
|
-
if (TailMatches(prevWords, [
|
|
1803
|
+
if (TailMatches(prevWords, ["DROP", "SEQUENCE"])) {
|
|
1786
1804
|
return completeTables(Query_for_list_of_sequences);
|
|
1787
1805
|
}
|
|
1788
|
-
if (TailMatches(prevWords, [
|
|
1806
|
+
if (TailMatches(prevWords, ["DROP", "TYPE"])) {
|
|
1789
1807
|
// Built-in scalar type keywords mirror upstream's
|
|
1790
1808
|
// `Keywords_for_list_of_datatypes` attached to the SchemaQuery; psql
|
|
1791
1809
|
// mixes them with user-defined types so `DROP TYPE big<TAB>` resolves
|
|
@@ -1796,56 +1814,56 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1796
1814
|
const types = await runCatalogQuery(conn, Query_for_list_of_types, currentWord);
|
|
1797
1815
|
return { candidates: [...keywords, ...types] };
|
|
1798
1816
|
}
|
|
1799
|
-
if (TailMatches(prevWords, [
|
|
1817
|
+
if (TailMatches(prevWords, ["DROP", "SCHEMA"])) {
|
|
1800
1818
|
if (!conn)
|
|
1801
1819
|
return { candidates: [] };
|
|
1802
1820
|
return {
|
|
1803
1821
|
candidates: await runCatalogQuery(conn, Query_for_list_of_schemas, currentWord),
|
|
1804
1822
|
};
|
|
1805
1823
|
}
|
|
1806
|
-
if (TailMatches(prevWords, [
|
|
1824
|
+
if (TailMatches(prevWords, ["DROP", "EXTENSION"])) {
|
|
1807
1825
|
if (!conn)
|
|
1808
1826
|
return { candidates: [] };
|
|
1809
1827
|
return {
|
|
1810
1828
|
candidates: await runCatalogQuery(conn, Query_for_list_of_extensions, currentWord),
|
|
1811
1829
|
};
|
|
1812
1830
|
}
|
|
1813
|
-
if (TailMatches(prevWords, [
|
|
1831
|
+
if (TailMatches(prevWords, ["DROP", "ROLE|USER|GROUP"])) {
|
|
1814
1832
|
if (!conn)
|
|
1815
1833
|
return { candidates: [] };
|
|
1816
1834
|
return {
|
|
1817
1835
|
candidates: await runCatalogQuery(conn, Query_for_list_of_roles, currentWord),
|
|
1818
1836
|
};
|
|
1819
1837
|
}
|
|
1820
|
-
if (TailMatches(prevWords, [
|
|
1838
|
+
if (TailMatches(prevWords, ["DROP", "DATABASE"])) {
|
|
1821
1839
|
if (!conn)
|
|
1822
1840
|
return { candidates: [] };
|
|
1823
1841
|
return {
|
|
1824
1842
|
candidates: await runCatalogQuery(conn, Query_for_list_of_databases, currentWord),
|
|
1825
1843
|
};
|
|
1826
1844
|
}
|
|
1827
|
-
if (TailMatches(prevWords, [
|
|
1845
|
+
if (TailMatches(prevWords, ["DROP", "FUNCTION"])) {
|
|
1828
1846
|
if (!conn)
|
|
1829
1847
|
return { candidates: [] };
|
|
1830
1848
|
return {
|
|
1831
1849
|
candidates: await runCatalogQuery(conn, Query_for_list_of_functions, currentWord),
|
|
1832
1850
|
};
|
|
1833
1851
|
}
|
|
1834
|
-
if (TailMatches(prevWords, [
|
|
1852
|
+
if (TailMatches(prevWords, ["DROP", "LANGUAGE"])) {
|
|
1835
1853
|
if (!conn)
|
|
1836
1854
|
return { candidates: [] };
|
|
1837
1855
|
return {
|
|
1838
1856
|
candidates: await runCatalogQuery(conn, Query_for_list_of_languages, currentWord),
|
|
1839
1857
|
};
|
|
1840
1858
|
}
|
|
1841
|
-
if (TailMatches(prevWords, [
|
|
1859
|
+
if (TailMatches(prevWords, ["DROP", "TABLESPACE"])) {
|
|
1842
1860
|
if (!conn)
|
|
1843
1861
|
return { candidates: [] };
|
|
1844
1862
|
return {
|
|
1845
1863
|
candidates: await runCatalogQuery(conn, Query_for_list_of_tablespaces, currentWord),
|
|
1846
1864
|
};
|
|
1847
1865
|
}
|
|
1848
|
-
if (TailMatches(prevWords, [
|
|
1866
|
+
if (TailMatches(prevWords, ["DROP", "PUBLICATION"])) {
|
|
1849
1867
|
// Mirrors upstream's `words_after_create` PUBLICATION entry
|
|
1850
1868
|
// (VersionedQuery on `Query_for_list_of_publications`). Two-step
|
|
1851
1869
|
// completion: `DROP PUBLIC<TAB>` first resolves to `PUBLICATION`
|
|
@@ -1857,7 +1875,7 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1857
1875
|
candidates: await runCatalogQuery(conn, Query_for_list_of_publications, currentWord),
|
|
1858
1876
|
};
|
|
1859
1877
|
}
|
|
1860
|
-
if (TailMatches(prevWords, [
|
|
1878
|
+
if (TailMatches(prevWords, ["DROP", "SUBSCRIPTION"])) {
|
|
1861
1879
|
// Same shape as DROP PUBLICATION — paired here for parity with the
|
|
1862
1880
|
// ALTER block above.
|
|
1863
1881
|
if (!conn)
|
|
@@ -1867,7 +1885,7 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1867
1885
|
};
|
|
1868
1886
|
}
|
|
1869
1887
|
// Bare DROP — sub-object keywords.
|
|
1870
|
-
if (TailMatches(prevWords, [
|
|
1888
|
+
if (TailMatches(prevWords, ["DROP"])) {
|
|
1871
1889
|
return {
|
|
1872
1890
|
candidates: filterAndCase(DROP_OBJECTS, currentWord, ctx.settings),
|
|
1873
1891
|
};
|
|
@@ -1875,44 +1893,44 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1875
1893
|
// ---- CREATE INDEX deep handling (specific arms BEFORE generic CREATE). ----
|
|
1876
1894
|
// CREATE INDEX <TAB> → CONCURRENTLY, IF NOT EXISTS, ON (no name = use ON
|
|
1877
1895
|
// directly), or a free-form index name.
|
|
1878
|
-
if (TailMatches(prevWords, [
|
|
1896
|
+
if (TailMatches(prevWords, ["CREATE", "INDEX"])) {
|
|
1879
1897
|
return {
|
|
1880
1898
|
candidates: filterAndCase(CREATE_INDEX_OPTIONS, currentWord, ctx.settings),
|
|
1881
1899
|
};
|
|
1882
1900
|
}
|
|
1883
|
-
if (TailMatches(prevWords, [
|
|
1901
|
+
if (TailMatches(prevWords, ["CREATE", "UNIQUE", "INDEX"])) {
|
|
1884
1902
|
return {
|
|
1885
1903
|
candidates: filterAndCase(CREATE_INDEX_OPTIONS, currentWord, ctx.settings),
|
|
1886
1904
|
};
|
|
1887
1905
|
}
|
|
1888
1906
|
// CREATE INDEX <name> <TAB> → ON.
|
|
1889
|
-
if (TailMatches(prevWords, [
|
|
1890
|
-
TailMatches(prevWords, [
|
|
1891
|
-
return { candidates: filterAndCase([
|
|
1907
|
+
if (TailMatches(prevWords, ["CREATE", "INDEX", MatchAny]) ||
|
|
1908
|
+
TailMatches(prevWords, ["CREATE", "UNIQUE", "INDEX", MatchAny])) {
|
|
1909
|
+
return { candidates: filterAndCase(["ON"], currentWord, ctx.settings) };
|
|
1892
1910
|
}
|
|
1893
1911
|
// CREATE INDEX ... ON <TAB> → tables.
|
|
1894
|
-
if (TailMatches(prevWords, [
|
|
1895
|
-
TailMatches(prevWords, [
|
|
1896
|
-
TailMatches(prevWords, [
|
|
1897
|
-
TailMatches(prevWords, [
|
|
1912
|
+
if (TailMatches(prevWords, ["CREATE", "INDEX", MatchAny, "ON"]) ||
|
|
1913
|
+
TailMatches(prevWords, ["CREATE", "INDEX", "ON"]) ||
|
|
1914
|
+
TailMatches(prevWords, ["CREATE", "UNIQUE", "INDEX", MatchAny, "ON"]) ||
|
|
1915
|
+
TailMatches(prevWords, ["CREATE", "UNIQUE", "INDEX", "ON"])) {
|
|
1898
1916
|
return completeTables();
|
|
1899
1917
|
}
|
|
1900
1918
|
// CREATE INDEX ... ON <table> <TAB> → USING / (.
|
|
1901
|
-
if ((HeadMatches(prevWords, [
|
|
1902
|
-
HeadMatches(prevWords, [
|
|
1903
|
-
TailMatches(prevWords, [
|
|
1919
|
+
if ((HeadMatches(prevWords, ["CREATE", "INDEX"]) ||
|
|
1920
|
+
HeadMatches(prevWords, ["CREATE", "UNIQUE", "INDEX"])) &&
|
|
1921
|
+
TailMatches(prevWords, ["ON", MatchAny])) {
|
|
1904
1922
|
return {
|
|
1905
|
-
candidates: filterAndCase([
|
|
1923
|
+
candidates: filterAndCase(["USING", "("], currentWord, ctx.settings),
|
|
1906
1924
|
};
|
|
1907
1925
|
}
|
|
1908
1926
|
// CREATE INDEX ... USING <TAB> → access methods.
|
|
1909
|
-
if ((HeadMatches(prevWords, [
|
|
1910
|
-
HeadMatches(prevWords, [
|
|
1911
|
-
TailMatches(prevWords, [
|
|
1927
|
+
if ((HeadMatches(prevWords, ["CREATE", "INDEX"]) ||
|
|
1928
|
+
HeadMatches(prevWords, ["CREATE", "UNIQUE", "INDEX"])) &&
|
|
1929
|
+
TailMatches(prevWords, ["USING"])) {
|
|
1912
1930
|
if (!conn) {
|
|
1913
1931
|
// Even without a connection, offer the built-in AMs as a fallback.
|
|
1914
1932
|
return {
|
|
1915
|
-
candidates: filterAndCase([
|
|
1933
|
+
candidates: filterAndCase(["btree", "hash", "gist", "gin", "spgist", "brin"], currentWord, ctx.settings),
|
|
1916
1934
|
};
|
|
1917
1935
|
}
|
|
1918
1936
|
return {
|
|
@@ -1920,12 +1938,12 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1920
1938
|
};
|
|
1921
1939
|
}
|
|
1922
1940
|
// CREATE ... — first sub-object keyword.
|
|
1923
|
-
if (TailMatches(prevWords, [
|
|
1941
|
+
if (TailMatches(prevWords, ["CREATE"])) {
|
|
1924
1942
|
return {
|
|
1925
1943
|
candidates: filterAndCase(CREATE_OBJECTS, currentWord, ctx.settings),
|
|
1926
1944
|
};
|
|
1927
1945
|
}
|
|
1928
|
-
if (TailMatches(prevWords, [
|
|
1946
|
+
if (TailMatches(prevWords, ["CREATE", "TABLE"])) {
|
|
1929
1947
|
// Upstream's `words_after_create` fallback (tab-complete.in.c
|
|
1930
1948
|
// ~lines 2062-2082) runs `Query_for_list_of_tables` when the
|
|
1931
1949
|
// word immediately before the cursor is `TABLE`. The intent is to
|
|
@@ -1937,31 +1955,38 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1937
1955
|
return completeTables();
|
|
1938
1956
|
}
|
|
1939
1957
|
// Inside CREATE TABLE column-list parens: `<col_name> <TAB>` → types.
|
|
1940
|
-
if (HeadMatches(prevWords, [
|
|
1941
|
-
TailMatches(prevWords, [
|
|
1958
|
+
if (HeadMatches(prevWords, ["CREATE", "TABLE"]) &&
|
|
1959
|
+
TailMatches(prevWords, ["(|,", MatchAny])) {
|
|
1942
1960
|
if (!conn)
|
|
1943
1961
|
return { candidates: [] };
|
|
1944
1962
|
return {
|
|
1945
1963
|
candidates: await runCatalogQuery(conn, Query_for_list_of_datatypes, currentWord),
|
|
1946
1964
|
};
|
|
1947
1965
|
}
|
|
1948
|
-
if (TailMatches(prevWords, [
|
|
1966
|
+
if (TailMatches(prevWords, ["CREATE", "OR", "REPLACE"])) {
|
|
1949
1967
|
return {
|
|
1950
|
-
candidates: filterAndCase([
|
|
1968
|
+
candidates: filterAndCase([
|
|
1969
|
+
"FUNCTION",
|
|
1970
|
+
"PROCEDURE",
|
|
1971
|
+
"VIEW",
|
|
1972
|
+
"TRIGGER",
|
|
1973
|
+
"AGGREGATE",
|
|
1974
|
+
"TRANSFORM",
|
|
1975
|
+
], currentWord, ctx.settings),
|
|
1951
1976
|
};
|
|
1952
1977
|
}
|
|
1953
1978
|
// TRUNCATE [TABLE] x
|
|
1954
|
-
if (TailMatches(prevWords, [
|
|
1979
|
+
if (TailMatches(prevWords, ["TRUNCATE"])) {
|
|
1955
1980
|
return {
|
|
1956
1981
|
candidates: [
|
|
1957
|
-
...filterAndCase([
|
|
1982
|
+
...filterAndCase(["TABLE", "ONLY"], currentWord, ctx.settings),
|
|
1958
1983
|
...(await tableCandidates(conn, currentWord)),
|
|
1959
1984
|
],
|
|
1960
1985
|
};
|
|
1961
1986
|
}
|
|
1962
|
-
if (TailMatches(prevWords, [
|
|
1987
|
+
if (TailMatches(prevWords, ["TRUNCATE", "TABLE"]))
|
|
1963
1988
|
return completeTables();
|
|
1964
|
-
if (TailMatches(prevWords, [
|
|
1989
|
+
if (TailMatches(prevWords, ["TRUNCATE", "ONLY"]))
|
|
1965
1990
|
return completeTables();
|
|
1966
1991
|
// COPY ... FROM <sth> WITH ( — option keywords inside the WITH
|
|
1967
1992
|
// parenthesised list. The tokenizer splits `(` and `,` into their
|
|
@@ -1973,16 +1998,16 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1973
1998
|
// `Copy_to_options`). The `HeadMatches` guard restricts the rule
|
|
1974
1999
|
// to a real COPY statement so the generic `(`/`,` pattern doesn't
|
|
1975
2000
|
// fire inside CREATE TABLE / SELECT lists.
|
|
1976
|
-
if (HeadMatches(prevWords, [
|
|
1977
|
-
HeadMatches(prevWords, [MatchAny, MatchAny,
|
|
1978
|
-
(TailMatches(prevWords, [
|
|
2001
|
+
if (HeadMatches(prevWords, ["COPY|\\copy"]) &&
|
|
2002
|
+
HeadMatches(prevWords, [MatchAny, MatchAny, "FROM"]) &&
|
|
2003
|
+
(TailMatches(prevWords, ["("]) || TailMatches(prevWords, [","]))) {
|
|
1979
2004
|
return {
|
|
1980
2005
|
candidates: filterAndCase(COPY_FROM_OPTIONS, currentWord, ctx.settings),
|
|
1981
2006
|
};
|
|
1982
2007
|
}
|
|
1983
|
-
if (HeadMatches(prevWords, [
|
|
1984
|
-
HeadMatches(prevWords, [MatchAny, MatchAny,
|
|
1985
|
-
(TailMatches(prevWords, [
|
|
2008
|
+
if (HeadMatches(prevWords, ["COPY|\\copy"]) &&
|
|
2009
|
+
HeadMatches(prevWords, [MatchAny, MatchAny, "TO"]) &&
|
|
2010
|
+
(TailMatches(prevWords, ["("]) || TailMatches(prevWords, [","]))) {
|
|
1986
2011
|
return {
|
|
1987
2012
|
candidates: filterAndCase(COPY_TO_OPTIONS, currentWord, ctx.settings),
|
|
1988
2013
|
};
|
|
@@ -1990,46 +2015,53 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
1990
2015
|
// COPY x → tables. (The `COPY x FROM/TO <path>` filename completion is
|
|
1991
2016
|
// handled by the early `isCopyFromOrTo` check at the top of this
|
|
1992
2017
|
// function so it wins over the generic `FROM <prefix>` table rule.)
|
|
1993
|
-
if (TailMatches(prevWords, [
|
|
2018
|
+
if (TailMatches(prevWords, ["COPY"]))
|
|
1994
2019
|
return completeTables();
|
|
1995
|
-
if (TailMatches(prevWords, [
|
|
2020
|
+
if (TailMatches(prevWords, ["COPY", MatchAny])) {
|
|
1996
2021
|
return {
|
|
1997
|
-
candidates: filterAndCase([
|
|
2022
|
+
candidates: filterAndCase(["FROM", "TO"], currentWord, ctx.settings),
|
|
1998
2023
|
};
|
|
1999
2024
|
}
|
|
2000
2025
|
// ANALYZE x → tables (optional VERBOSE first).
|
|
2001
|
-
if (TailMatches(prevWords, [
|
|
2002
|
-
TailMatches(prevWords, [
|
|
2026
|
+
if (TailMatches(prevWords, ["ANALYZE"]) ||
|
|
2027
|
+
TailMatches(prevWords, ["ANALYZE", "VERBOSE"])) {
|
|
2003
2028
|
return completeTables();
|
|
2004
2029
|
}
|
|
2005
2030
|
// VACUUM x → tables.
|
|
2006
|
-
if (TailMatches(prevWords, [
|
|
2007
|
-
TailMatches(prevWords, [
|
|
2031
|
+
if (TailMatches(prevWords, ["VACUUM"]) ||
|
|
2032
|
+
TailMatches(prevWords, ["VACUUM", "VERBOSE"])) {
|
|
2008
2033
|
return completeTables();
|
|
2009
2034
|
}
|
|
2010
|
-
if (TailMatches(prevWords, [
|
|
2035
|
+
if (TailMatches(prevWords, ["VACUUM", "FULL"]))
|
|
2011
2036
|
return completeTables();
|
|
2012
|
-
if (TailMatches(prevWords, [
|
|
2037
|
+
if (TailMatches(prevWords, ["VACUUM", "ANALYZE"]))
|
|
2013
2038
|
return completeTables();
|
|
2014
2039
|
// REINDEX [TABLE|INDEX|SCHEMA|DATABASE] x
|
|
2015
|
-
if (TailMatches(prevWords, [
|
|
2040
|
+
if (TailMatches(prevWords, ["REINDEX"])) {
|
|
2016
2041
|
return {
|
|
2017
|
-
candidates: filterAndCase([
|
|
2042
|
+
candidates: filterAndCase([
|
|
2043
|
+
"TABLE",
|
|
2044
|
+
"INDEX",
|
|
2045
|
+
"SCHEMA",
|
|
2046
|
+
"DATABASE",
|
|
2047
|
+
"SYSTEM",
|
|
2048
|
+
"CONCURRENTLY",
|
|
2049
|
+
], currentWord, ctx.settings),
|
|
2018
2050
|
};
|
|
2019
2051
|
}
|
|
2020
|
-
if (TailMatches(prevWords, [
|
|
2052
|
+
if (TailMatches(prevWords, ["REINDEX", "TABLE"]))
|
|
2021
2053
|
return completeTables();
|
|
2022
|
-
if (TailMatches(prevWords, [
|
|
2054
|
+
if (TailMatches(prevWords, ["REINDEX", "INDEX"])) {
|
|
2023
2055
|
return completeTables(Query_for_list_of_indexes);
|
|
2024
2056
|
}
|
|
2025
|
-
if (TailMatches(prevWords, [
|
|
2057
|
+
if (TailMatches(prevWords, ["REINDEX", "SCHEMA"])) {
|
|
2026
2058
|
if (!conn)
|
|
2027
2059
|
return { candidates: [] };
|
|
2028
2060
|
return {
|
|
2029
2061
|
candidates: await runCatalogQuery(conn, Query_for_list_of_schemas, currentWord),
|
|
2030
2062
|
};
|
|
2031
2063
|
}
|
|
2032
|
-
if (TailMatches(prevWords, [
|
|
2064
|
+
if (TailMatches(prevWords, ["REINDEX", "DATABASE"])) {
|
|
2033
2065
|
if (!conn)
|
|
2034
2066
|
return { candidates: [] };
|
|
2035
2067
|
return {
|
|
@@ -2037,25 +2069,27 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
2037
2069
|
};
|
|
2038
2070
|
}
|
|
2039
2071
|
// GRANT … ON … TO …
|
|
2040
|
-
if (TailMatches(prevWords, [
|
|
2072
|
+
if (TailMatches(prevWords, ["GRANT"]) ||
|
|
2073
|
+
TailMatches(prevWords, ["REVOKE"])) {
|
|
2041
2074
|
return {
|
|
2042
2075
|
candidates: filterAndCase(PRIVILEGE_KEYWORDS, currentWord, ctx.settings),
|
|
2043
2076
|
};
|
|
2044
2077
|
}
|
|
2045
|
-
if (TailMatches(prevWords, [
|
|
2078
|
+
if (TailMatches(prevWords, ["ON"])) {
|
|
2046
2079
|
// Could be either GRANT/REVOKE … ON or CREATE INDEX … ON. We try
|
|
2047
2080
|
// tables; if the prior keyword set is CREATE INDEX the rule above
|
|
2048
2081
|
// already short-circuited.
|
|
2049
2082
|
return completeTables();
|
|
2050
2083
|
}
|
|
2051
|
-
if (TailMatches(prevWords, [
|
|
2052
|
-
if (HeadMatches(prevWords, [
|
|
2084
|
+
if (TailMatches(prevWords, ["TO"])) {
|
|
2085
|
+
if (HeadMatches(prevWords, ["GRANT"]) && conn) {
|
|
2053
2086
|
return {
|
|
2054
2087
|
candidates: await runCatalogQuery(conn, Query_for_list_of_roles, currentWord),
|
|
2055
2088
|
};
|
|
2056
2089
|
}
|
|
2057
2090
|
}
|
|
2058
|
-
if (TailMatches(prevWords, [
|
|
2091
|
+
if (TailMatches(prevWords, ["FROM"]) &&
|
|
2092
|
+
HeadMatches(prevWords, ["REVOKE"])) {
|
|
2059
2093
|
if (!conn)
|
|
2060
2094
|
return { candidates: [] };
|
|
2061
2095
|
return {
|
|
@@ -2063,45 +2097,45 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
2063
2097
|
};
|
|
2064
2098
|
}
|
|
2065
2099
|
// LOCK [TABLE] x
|
|
2066
|
-
if (TailMatches(prevWords, [
|
|
2100
|
+
if (TailMatches(prevWords, ["LOCK"])) {
|
|
2067
2101
|
return {
|
|
2068
2102
|
candidates: [
|
|
2069
|
-
...filterAndCase([
|
|
2103
|
+
...filterAndCase(["TABLE"], currentWord, ctx.settings),
|
|
2070
2104
|
...(await tableCandidates(conn, currentWord)),
|
|
2071
2105
|
],
|
|
2072
2106
|
};
|
|
2073
2107
|
}
|
|
2074
|
-
if (TailMatches(prevWords, [
|
|
2108
|
+
if (TailMatches(prevWords, ["LOCK", "TABLE"]))
|
|
2075
2109
|
return completeTables();
|
|
2076
2110
|
// SET search_path, SET ROLE, SET SCHEMA, etc.
|
|
2077
|
-
if (TailMatches(prevWords, [
|
|
2111
|
+
if (TailMatches(prevWords, ["SET", "ROLE"])) {
|
|
2078
2112
|
if (!conn)
|
|
2079
2113
|
return { candidates: [] };
|
|
2080
2114
|
return {
|
|
2081
2115
|
candidates: await runCatalogQuery(conn, Query_for_list_of_roles, currentWord),
|
|
2082
2116
|
};
|
|
2083
2117
|
}
|
|
2084
|
-
if (TailMatches(prevWords, [
|
|
2118
|
+
if (TailMatches(prevWords, ["SET", "SCHEMA"])) {
|
|
2085
2119
|
if (!conn)
|
|
2086
2120
|
return { candidates: [] };
|
|
2087
2121
|
return {
|
|
2088
2122
|
candidates: await runCatalogQuery(conn, Query_for_list_of_schemas, currentWord),
|
|
2089
2123
|
};
|
|
2090
2124
|
}
|
|
2091
|
-
if (TailMatches(prevWords, [
|
|
2125
|
+
if (TailMatches(prevWords, ["SET", "SESSION"])) {
|
|
2092
2126
|
return {
|
|
2093
|
-
candidates: filterAndCase([
|
|
2127
|
+
candidates: filterAndCase(["AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION"], currentWord, ctx.settings),
|
|
2094
2128
|
};
|
|
2095
2129
|
}
|
|
2096
|
-
if (TailMatches(prevWords, [
|
|
2130
|
+
if (TailMatches(prevWords, ["SET", "TRANSACTION"])) {
|
|
2097
2131
|
return {
|
|
2098
|
-
candidates: filterAndCase([
|
|
2132
|
+
candidates: filterAndCase(["ISOLATION LEVEL", "READ ONLY", "READ WRITE", "DEFERRABLE"], currentWord, ctx.settings),
|
|
2099
2133
|
};
|
|
2100
2134
|
}
|
|
2101
2135
|
// `SET <name> TO|= <TAB>` — for DateStyle we can suggest the formats.
|
|
2102
|
-
if (TailMatches(prevWords, [
|
|
2103
|
-
TailMatches(prevWords, [
|
|
2104
|
-
TailMatches(prevWords, [
|
|
2136
|
+
if (TailMatches(prevWords, ["SET", "DateStyle", "TO|="]) ||
|
|
2137
|
+
TailMatches(prevWords, ["SET", "DATESTYLE", "TO|="]) ||
|
|
2138
|
+
TailMatches(prevWords, ["SET", "datestyle", "TO|="])) {
|
|
2105
2139
|
return {
|
|
2106
2140
|
candidates: filterAndCase(DATESTYLE_VALUES, currentWord, ctx.settings),
|
|
2107
2141
|
};
|
|
@@ -2118,9 +2152,9 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
2118
2152
|
// pattern against the quoted form so the partial `'America/New_`
|
|
2119
2153
|
// resolves correctly.
|
|
2120
2154
|
// Mirrors upstream tab-complete.in.c ~line 4530.
|
|
2121
|
-
if (TailMatches(prevWords, [
|
|
2122
|
-
TailMatches(prevWords, [
|
|
2123
|
-
TailMatches(prevWords, [
|
|
2155
|
+
if (TailMatches(prevWords, ["SET", "timezone", "TO|="]) ||
|
|
2156
|
+
TailMatches(prevWords, ["SET", "TIMEZONE", "TO|="]) ||
|
|
2157
|
+
TailMatches(prevWords, ["SET", "TimeZone", "TO|="])) {
|
|
2124
2158
|
if (!conn)
|
|
2125
2159
|
return { candidates: [] };
|
|
2126
2160
|
const query = currentWord.startsWith("'")
|
|
@@ -2136,7 +2170,7 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
2136
2170
|
// value completion; non-enum GUCs return an empty rowset (no candidates)
|
|
2137
2171
|
// — matching upstream, which also emits nothing for unknown GUCs once a
|
|
2138
2172
|
// value position is reached.
|
|
2139
|
-
if (TailMatches(prevWords, [
|
|
2173
|
+
if (TailMatches(prevWords, ["SET", MatchAny, "TO|="])) {
|
|
2140
2174
|
if (!conn)
|
|
2141
2175
|
return { candidates: [] };
|
|
2142
2176
|
// Walk back to the GUC name (the word before TO/=).
|
|
@@ -2150,21 +2184,21 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
2150
2184
|
// single unique completion so `set foo<tab><tab>` resolves to
|
|
2151
2185
|
// `set foo TO ` rather than listing two near-synonymous separators.
|
|
2152
2186
|
// Verified against vanilla psql 18 + upstream test line 366.
|
|
2153
|
-
if (TailMatches(prevWords, [
|
|
2187
|
+
if (TailMatches(prevWords, ["SET", MatchAny])) {
|
|
2154
2188
|
return {
|
|
2155
|
-
candidates: filterAndCase([
|
|
2189
|
+
candidates: filterAndCase(["TO"], currentWord, ctx.settings),
|
|
2156
2190
|
};
|
|
2157
2191
|
}
|
|
2158
2192
|
// Bare SET <TAB>: GUC name OR top-level SET sub-keywords (ROLE, SCHEMA, …).
|
|
2159
|
-
if (TailMatches(prevWords, [
|
|
2193
|
+
if (TailMatches(prevWords, ["SET"])) {
|
|
2160
2194
|
const staticKw = filterAndCase([
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2195
|
+
"CONSTRAINTS",
|
|
2196
|
+
"LOCAL",
|
|
2197
|
+
"ROLE",
|
|
2198
|
+
"SCHEMA",
|
|
2199
|
+
"SESSION",
|
|
2200
|
+
"TIME ZONE",
|
|
2201
|
+
"TRANSACTION",
|
|
2168
2202
|
], currentWord, ctx.settings);
|
|
2169
2203
|
if (!conn)
|
|
2170
2204
|
return { candidates: staticKw };
|
|
@@ -2172,21 +2206,21 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
2172
2206
|
return { candidates: [...staticKw, ...guc] };
|
|
2173
2207
|
}
|
|
2174
2208
|
// SHOW <TAB> — ALL keyword plus the live GUC list.
|
|
2175
|
-
if (TailMatches(prevWords, [
|
|
2176
|
-
const staticKw = filterAndCase([
|
|
2209
|
+
if (TailMatches(prevWords, ["SHOW"])) {
|
|
2210
|
+
const staticKw = filterAndCase(["ALL"], currentWord, ctx.settings);
|
|
2177
2211
|
if (!conn) {
|
|
2178
2212
|
return {
|
|
2179
2213
|
candidates: [
|
|
2180
2214
|
...staticKw,
|
|
2181
2215
|
...filterAndCase([
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2216
|
+
"search_path",
|
|
2217
|
+
"role",
|
|
2218
|
+
"session_authorization",
|
|
2219
|
+
"transaction_isolation",
|
|
2220
|
+
"client_encoding",
|
|
2221
|
+
"server_encoding",
|
|
2222
|
+
"server_version",
|
|
2223
|
+
"timezone",
|
|
2190
2224
|
], currentWord, ctx.settings),
|
|
2191
2225
|
],
|
|
2192
2226
|
};
|
|
@@ -2195,47 +2229,48 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
2195
2229
|
return { candidates: [...staticKw, ...guc] };
|
|
2196
2230
|
}
|
|
2197
2231
|
// RESET <TAB> — ALL or the live GUC list.
|
|
2198
|
-
if (TailMatches(prevWords, [
|
|
2199
|
-
const staticKw = filterAndCase([
|
|
2232
|
+
if (TailMatches(prevWords, ["RESET"])) {
|
|
2233
|
+
const staticKw = filterAndCase(["ALL", "SESSION AUTHORIZATION", "ROLE"], currentWord, ctx.settings);
|
|
2200
2234
|
if (!conn)
|
|
2201
2235
|
return { candidates: staticKw };
|
|
2202
2236
|
const guc = await runCatalogQuery(conn, Query_for_list_of_set_vars, currentWord);
|
|
2203
2237
|
return { candidates: [...staticKw, ...guc] };
|
|
2204
2238
|
}
|
|
2205
2239
|
// START / BEGIN [TRANSACTION] …
|
|
2206
|
-
if (TailMatches(prevWords, [
|
|
2240
|
+
if (TailMatches(prevWords, ["BEGIN"]) ||
|
|
2241
|
+
TailMatches(prevWords, ["START"])) {
|
|
2207
2242
|
return {
|
|
2208
2243
|
candidates: filterAndCase(TRANSACTION_KEYWORDS, currentWord, ctx.settings),
|
|
2209
2244
|
};
|
|
2210
2245
|
}
|
|
2211
2246
|
// COMMIT / ROLLBACK / RELEASE / SAVEPOINT - small completions
|
|
2212
|
-
if (TailMatches(prevWords, [
|
|
2247
|
+
if (TailMatches(prevWords, ["ROLLBACK"])) {
|
|
2213
2248
|
return {
|
|
2214
|
-
candidates: filterAndCase([
|
|
2249
|
+
candidates: filterAndCase(["TO SAVEPOINT", "TRANSACTION", "AND CHAIN", "AND NO CHAIN"], currentWord, ctx.settings),
|
|
2215
2250
|
};
|
|
2216
2251
|
}
|
|
2217
2252
|
// EXPLAIN … — pass through to SELECT-/INSERT-/UPDATE-style rules by
|
|
2218
2253
|
// letting subsequent words drive completion. For the first word after
|
|
2219
2254
|
// EXPLAIN, offer the options + statement keywords.
|
|
2220
|
-
if (TailMatches(prevWords, [
|
|
2255
|
+
if (TailMatches(prevWords, ["EXPLAIN"])) {
|
|
2221
2256
|
return {
|
|
2222
2257
|
candidates: filterAndCase([
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2258
|
+
"ANALYZE",
|
|
2259
|
+
"VERBOSE",
|
|
2260
|
+
"SELECT",
|
|
2261
|
+
"INSERT INTO",
|
|
2262
|
+
"UPDATE",
|
|
2263
|
+
"DELETE FROM",
|
|
2264
|
+
"(",
|
|
2230
2265
|
], currentWord, ctx.settings),
|
|
2231
2266
|
};
|
|
2232
2267
|
}
|
|
2233
2268
|
// DECLARE … CURSOR FOR …
|
|
2234
|
-
if (TailMatches(prevWords, [
|
|
2269
|
+
if (TailMatches(prevWords, ["DECLARE"])) {
|
|
2235
2270
|
return { candidates: [] };
|
|
2236
2271
|
}
|
|
2237
2272
|
// CALL / DO — no completion beyond keywords (procedure args / language).
|
|
2238
|
-
if (TailMatches(prevWords, [
|
|
2273
|
+
if (TailMatches(prevWords, ["CALL"])) {
|
|
2239
2274
|
if (!conn)
|
|
2240
2275
|
return { candidates: [] };
|
|
2241
2276
|
return {
|
|
@@ -2243,27 +2278,29 @@ const sqlRules = async (prevWords, currentWord, ctx, conn) => {
|
|
|
2243
2278
|
};
|
|
2244
2279
|
}
|
|
2245
2280
|
// After SELECT — offer FROM / common functions.
|
|
2246
|
-
if (TailMatches(prevWords, [
|
|
2281
|
+
if (TailMatches(prevWords, ["SELECT"])) {
|
|
2247
2282
|
// The next word can be anything (column list); offer DISTINCT/ALL/* as a
|
|
2248
2283
|
// small hint set.
|
|
2249
2284
|
return {
|
|
2250
2285
|
candidates: filterAndCase([
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2286
|
+
"DISTINCT",
|
|
2287
|
+
"ALL",
|
|
2288
|
+
"*",
|
|
2289
|
+
"CURRENT_DATE",
|
|
2290
|
+
"CURRENT_TIME",
|
|
2291
|
+
"CURRENT_TIMESTAMP",
|
|
2292
|
+
"CURRENT_USER",
|
|
2293
|
+
"NULL",
|
|
2294
|
+
"TRUE",
|
|
2295
|
+
"FALSE",
|
|
2261
2296
|
], currentWord, ctx.settings),
|
|
2262
2297
|
};
|
|
2263
2298
|
}
|
|
2264
2299
|
// Trailing-keyword fallthrough: WHERE, ORDER BY, GROUP BY, LIMIT etc.
|
|
2265
|
-
if (TailMatches(prevWords, [
|
|
2266
|
-
return {
|
|
2300
|
+
if (TailMatches(prevWords, ["SELECT", "*"])) {
|
|
2301
|
+
return {
|
|
2302
|
+
candidates: filterAndCase(["FROM"], currentWord, ctx.settings),
|
|
2303
|
+
};
|
|
2267
2304
|
}
|
|
2268
2305
|
// No specific rule fired.
|
|
2269
2306
|
return { candidates: [] };
|
|
@@ -2309,14 +2346,14 @@ const completeSchemaOrRelations = async (conn, word, query) => {
|
|
|
2309
2346
|
const canonicalSchema = split.schemaWasQuoted
|
|
2310
2347
|
? split.schema
|
|
2311
2348
|
: split.schema.toLowerCase();
|
|
2312
|
-
return rows.map((r) => canonicalSchema +
|
|
2349
|
+
return rows.map((r) => canonicalSchema + "." + r);
|
|
2313
2350
|
}
|
|
2314
2351
|
// Unqualified: combine relations + schemas (schemas suffixed with `.`).
|
|
2315
2352
|
const [rels, schemas] = await Promise.all([
|
|
2316
2353
|
runCatalogQuery(conn, query, word),
|
|
2317
2354
|
runCatalogQuery(conn, Query_for_list_of_schemas, word),
|
|
2318
2355
|
]);
|
|
2319
|
-
return [...rels, ...schemas.map((s) => s +
|
|
2356
|
+
return [...rels, ...schemas.map((s) => s + ".")];
|
|
2320
2357
|
};
|
|
2321
2358
|
/**
|
|
2322
2359
|
* Search the catalog for relations matching a user-supplied prefix that
|
|
@@ -2328,7 +2365,7 @@ const completeSchemaOrRelations = async (conn, word, query) => {
|
|
|
2328
2365
|
*/
|
|
2329
2366
|
const completeQuotedRelations = async (conn, word, query) => {
|
|
2330
2367
|
// Strip leading `"` (and any trailing `"` the user pre-typed).
|
|
2331
|
-
const inside = word.slice(1).replace(/"$/,
|
|
2368
|
+
const inside = word.slice(1).replace(/"$/, "");
|
|
2332
2369
|
// Use a case-sensitive raw-relname LIKE — the inside-the-quote portion
|
|
2333
2370
|
// is taken verbatim.
|
|
2334
2371
|
const sql = caseSensitiveRelnameVariant(query);
|
|
@@ -2351,13 +2388,13 @@ const caseSensitiveRelnameVariant = (sql) => {
|
|
|
2351
2388
|
// We rewrite the SELECT/WHERE clauses on the standard relation queries.
|
|
2352
2389
|
// The only shape we need to support is `c.relname ILIKE $1` against
|
|
2353
2390
|
// `pg_catalog.pg_class c`, with various `c.relkind IN (...)` filters.
|
|
2354
|
-
if (!sql.includes(
|
|
2391
|
+
if (!sql.includes("pg_catalog.pg_class c"))
|
|
2355
2392
|
return null;
|
|
2356
|
-
if (!sql.includes(
|
|
2393
|
+
if (!sql.includes("c.relname ILIKE $1"))
|
|
2357
2394
|
return null;
|
|
2358
2395
|
return sql
|
|
2359
|
-
.replace(
|
|
2360
|
-
.replace(
|
|
2396
|
+
.replace("SELECT pg_catalog.quote_ident(c.relname)", "SELECT c.relname")
|
|
2397
|
+
.replace("c.relname ILIKE $1", "c.relname LIKE $1");
|
|
2361
2398
|
};
|
|
2362
2399
|
/** Case-insensitive prefix filter; preserves the candidate's original casing. */
|
|
2363
2400
|
const filterCi = (candidates, prefix) => {
|